Winform 在DataGrid中签入Combo_.NET_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > .NET > Winform 在DataGrid中签入Combo

Winform 在DataGrid中签入Combo

 2013/8/4 15:08:21  冲动  博客园  我要评论(0)
  • 摘要:背景最近看了Winform在DataGrid中怎么嵌入Combo,想到平时项目中写到的一些临时小工具,经常用配置参数,有些配置是简单的地址或文本,有些则是类似1代表SQL,2代表Oracle等。于是想结合刚刚学的知识,做一个示例。关于参数的保存,想到用数据库,简单点就是用SQLite,可以无需安装数据库,后来想想,干脆用文件进行存储,这样简单,而且.net对Json的支持很好。资源下载示例代码实现1.设计数据结构。publicclassListItem{publicList<
  • 标签:for tag winform

背景

  最近看了Winform在DataGrid中怎么嵌入Combo,想到平时项目中写到的一些临时小工具,经常用配置参数,有些配置是简单的地址或文本,有些则是类似1代表SQL,2代表Oracle等。于是想结合刚刚学的知识,做一个示例。

  关于参数的保存,想到用数据库,简单点就是用SQLite,可以无需安装数据库,后来想想,干脆用文件进行存储,这样简单,而且.net对Json的支持很好。

资源下载

  示例代码

  

  

实现

  1.设计数据结构。

class="code_img_closed" src="/Upload/Images/2013080415/0015B68B3C38AA5B.gif" alt="" />logs_code_hide('a97303af-c3f7-4915-aad9-80dd5e20b21f',event)" src="/Upload/Images/2013080415/2B1B950FA3DF188F.gif" alt="" />
    public class ListItem
    {
        public List<ListItem> lstItem = new List<ListItem>();
        public string Text { get; set; }
        public object Value { get; set; }

        public ListItem() { }
        public ListItem(string pText, string pValue) { Text = pText; Value = pValue; }

        public override string ToString()
        {
            return Text;
        }
    }
Combo Item数据结构
    public class ConfigRow
    {
        public string Name { get; set; }//参数名称
        public string Text { get; set; }//参数显示值
        public string Value { get; set; }//参数真实值
        public string Description { get; set; }//参数描述
        public int Type { get; set; }//参数类别 1 常规字符  2 下拉框
        public List<ListItem> lstItem { get; set; }//参数下拉框数据源列表
        #region 数据源操作
        //得到数据源组织的字符串
        public string GetItemText()
        {
            var ret = new StringBuilder();
            foreach (var li in lstItem)
            {
                ret.AppendLine(li.Value + "|" + li.Text);
            }
            return ret.ToString();
        }
        //根据格式化字符串设置数据源
        public void SetItem(string text)
        {
            if (lstItem == null)
                lstItem = new List<ListItem>();
            else
                lstItem.Clear();
            var arr = text.Trim('\r').Split('\n');
            foreach (var a in arr)
            {
                if (a.Length > 0)
                {
                    var item = a.Split('|');
                    if (item.Length > 0)
                    {
                        ListItem li = new ListItem();
                        li.Value = item[0];
                        li.Text = item[1];
                        lstItem.Add(li);
                    }
                }
            }
        }
        //检查某项是否存在数据源中
        public bool CheckItem(string text, string value)
        {
            var index = lstItem.FindIndex((item) =>
            {
                return item.Text == text && item.Value.ToString() == value;
            });
            return index > -1;
        }
        #endregion
    }
配置参数实体 数据结构
    public class MyConfig
    {
        #region 公共成员
        public ThreadStart ComboChange { get; set; } //下拉框改变事件
        public string Path = @"./1.json";//文件保存路径
        private List<ConfigRow> lstRow { get; set; } //所有配置行
        #endregion

        #region 私有成员
        private ComboBox cbb;
        private DataGridView dgv;
        private MyConfig() { }
        #endregion

        #region 控件设置与事件
        private void Load()
        {
            #region DataGridView UI
            var clName = new System.Windows.Forms.DataGridViewTextBoxColumn();
            var clValue = new System.Windows.Forms.DataGridViewTextBoxColumn();
            var clDesp = new System.Windows.Forms.DataGridViewTextBoxColumn();
            var clType = new System.Windows.Forms.DataGridViewTextBoxColumn();
            this.dgv.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
            clName,
           clValue,
            clDesp,
            clType});
            // 
            // clName
            // 
            clName.DataPropertyName = "Name";
            clName.HeaderText = "参数名称";
            clName.Name = "clName";
            clName.ReadOnly = true;
            clName.Width = (int)Math.Floor(dgv.Width * 0.2);
            // 
            // clValue
            // 
            clValue.DataPropertyName = "Text";
            clValue.HeaderText = "参数内容";
            clValue.Name = "clValue";
            clValue.Width = (int)Math.Floor(dgv.Width * 0.3);
            // 
            // clDesp
            // 
            clDesp.DataPropertyName = "Description";
            clDesp.HeaderText = "描述";
            clDesp.Name = "clDesp";
            clDesp.ReadOnly = true;
            clDesp.Width = (int)Math.Floor(dgv.Width * 0.5);
            // 
            // clType
            // 
            clType.DataPropertyName = "Type";
            clType.HeaderText = "参数状态";
            clType.Name = "clType";
            clType.ReadOnly = true;
            clType.Visible = false;
            #endregion
            //其他属性设置
            cbb = new ComboBox();
            cbb.Visible = false;
            cbb.DropDownStyle = ComboBoxStyle.DropDownList;
            dgv.AutoGenerateColumns = false;//不允许自动创建列
            dgv.Controls.Add(cbb);
            //绑定数据源
            if (lstRow != null && lstRow.Count != 0) dgv.DataSource = lstRow;
            //注册控件事件
            dgv.CurrentCellDirtyStateChanged += CurrentCellDirtyStateChanged;
            dgv.CurrentCellChanged += CurrentCellChanged;
            dgv.ColumnWidthChanged += ColumnWidthChanged;
            cbb.SelectedIndexChanged += SelectedIndexChanged;
            dgv.RowPostPaint += RowPostPaint;
        }
        private void CurrentCellDirtyStateChanged(object sender, EventArgs e)
        {
            var currentRow = dgv.CurrentRow.DataBoundItem as ConfigRow;
            if (currentRow.Type != 2) //下拉框类别单元格,在更改下拉框时已修改,此处忽略
            {
                if (dgv.CurrentCell.Value == null)
                    currentRow.Value = currentRow.Text = string.Empty;
                else
                    currentRow.Value = currentRow.Text = dgv.CurrentCell.Value.ToString();
            }
            Update(currentRow);
        }
        private void CurrentCellChanged(object sender, EventArgs e)
        {
            if (dgv.CurrentCell == null) return;
            //首先清空该事件 否则连续点击2个下拉框执行时有错误
            if (ComboChange != null) ComboChange = null;
            //若点击的是Value列,而且该参数类别为下拉框
            if (dgv.CurrentCell.OwningColumn.Name == "clValue" && dgv.CurrentRow.Cells["clType"].Value.ToString() == "2")
            {
                var current = dgv.CurrentRow.DataBoundItem as ConfigRow;
                cbb.DataSource = current.lstItem;
                cbb.Text = dgv.CurrentCell.Value.ToString();
                //设置下拉框的位置
                var rect = dgv.GetCellDisplayRectangle(dgv.CurrentCell.ColumnIndex, dgv.CurrentCell.RowIndex, false);
                cbb.Visible = true;
                cbb.Bounds = rect;
                //注册下拉框事件
                ComboChange = new ThreadStart(() =>
                {
                    var li = cbb.SelectedItem as ListItem;
                    //若值发生变更,则更新DataGridView以及绑定的数据源
                    if (li.Text != dgv.CurrentCell.Value.ToString())
                    {
                        dgv.CurrentCell.Value = li.Text;
                        current.Text = li.Text;
                        current.Value = li.Value.ToString();
                        //这里是引用传递,修改后直接体现在DataBoundItem属性上 无需再次赋值
                        //dataGridView1.CurrentRow.DataBoundItem = current;
                        //下拉框直接赋值将不会触发CurrentCellDirtyStateChanged事件 直接更新
                        Update(current);
                    }
                });
            }
            else
                cbb.Visible = false;
        }
        private void ColumnWidthChanged(object sender, DataGridViewColumnEventArgs e)
        {
            dgv.ClearSelection();
            cbb.Visible = false;
        }
        private void RowPostPaint(object sender, DataGridViewRowPostPaintEventArgs e)
        {
            SolidBrush b = new SolidBrush(dgv.RowHeadersDefaultCellStyle.ForeColor);
            e.Graphics.DrawString((e.RowIndex + 1).ToString(System.Globalization.CultureInfo.CurrentUICulture),
            dgv.DefaultCellStyle.Font, b, e.RowBounds.Location.X + 20, e.RowBounds.Location.Y + 4);
        }
        private void SelectedIndexChanged(object sender, EventArgs e)
        {
            if (ComboChange != null) ComboChange();
        }
        #endregion

        #region 加载文件
        //根据路径加载配置文件 并显示在DataGridView控件
        public static MyConfig Load(DataGridView dataGridView1, string path)
        {
            MyConfig my = new MyConfig();
            my.dgv = dataGridView1;
            try
            {
                var json = File.ReadAllText(path);
                my.lstRow = JsonConvert.DeserializeObject<List<ConfigRow>>(json);
            }
            catch
            {
                my.lstRow = new List<ConfigRow>();
            }
            my.Load();
            return my;
        }
        //根据路径加载配置文件
        public static MyConfig Load(string path)
        {
            MyConfig my = new MyConfig();
            try
            {
                var json = File.ReadAllText(path);
                my.lstRow = JsonConvert.DeserializeObject<List<ConfigRow>>(json);
            }
            catch
            {
                my.lstRow = new List<ConfigRow>();
            }
            return my;
        }
        //保存
        private void Save()
        {
            if (dgv != null)
            {
                dgv.DataSource = null;
                dgv.DataSource = lstRow;
            }
            var json = JsonConvert.SerializeObject(lstRow);
            File.WriteAllText(Path, json);
        }
        #endregion

        #region 增删改查
        //增加配置
        public void Add(ConfigRow row)
        {
            var index = lstRow.FindIndex((config) => { return config.Name == row.Name; });
            if (index == -1) lstRow.Add(row); //找到则更新 未找到则添加
            else lstRow[index] = row;
            Save();
        }
        //删除配置
        public bool Remove(string name)
        {
            var index = lstRow.FindIndex((config) => { return config.Name == name; });
            if (index == -1) return false;
            lstRow.RemoveAt(index);
            Save();
            //删除最后一行时不会出发CurrentCellChanged事件,下拉框可能未被隐藏
            if (lstRow.Count == 0 && cbb != null && cbb.Visible) cbb.Visible = false;
            return true;
        }
        //更新配置
        public bool Update(ConfigRow row)
        {
            var index = lstRow.FindIndex((config) => { return config.Name == row.Name; });
            if (index == -1) return false;
            else lstRow[index] = row;
            Save();
            return true;
        }
        //查询配置
        public ConfigRow Find(string name)
        {
            return lstRow.Find((config) => { return config.Name == name; });
        }
        #endregion

        #region 读取某项的值,并指定默认值
        //根据Name读取配置
        public string GetString(string name, string defaultValue)
        {
            var currentRow = Find(name);
            if (currentRow == null) return defaultValue;
            return currentRow.Value;
        }
        //根据Name读取配置
        public int GetInt(string name, int defaultValue)
        {
            var currentRow = lstRow.Find((config) => { return config.Name == name; });
            if (currentRow == null) return defaultValue;
            int value;
            if (Int32.TryParse(currentRow.Value, out value))
                return value;
            return defaultValue;
        }
        #endregion

        //测试
        public static MyConfig Create(DataGridView dgv)
        {
            var my = new MyConfig();
            my.lstRow = new List<ConfigRow>();
            //添加配置项 用户姓名
            var row1 = new ConfigRow();
            row1.Name = "UserName";
            row1.Value = "admin";
            row1.Text = "admin";
            row1.Description = "配置用户的姓名";
            row1.Type = 1;//常规字符
            my.lstRow.Add(row1);

            //添加配置项 地址
            var row2 = new ConfigRow();
            row2.Name = "UserAddress";
            row2.Value = "湖南省长沙市";
            row2.Text = "湖南省长沙市";
            row2.Description = "配置用户的地址";
            row2.Type = 1;//常规字符
            my.lstRow.Add(row2);

            //添加配置项 性别
            var row3 = new ConfigRow();
            row3.Name = "UserSex";
            row3.Value = "1";
            row3.Text = "";
            row3.Description = "配置用户的性别";
            row3.Type = 2;//下拉数据源
            //非常规字符必须添加数据源
            var item = new ListItem();
            item.Text = "";
            item.Value = "1";
            var item2 = new ListItem();
            item2.Text = "";
            item2.Value = "0";
            row3.lstItem = new List<ListItem>() { item, item2 };
            my.lstRow.Add(row3);

            //添加配置项 年龄
            var row4 = new ConfigRow();
            row4.Name = "UserAge";
            row4.Value = "15";
            row4.Text = "15岁";
            row4.Description = "配置用户的年龄";
            row4.Type = 2;//下拉数据源
            //非常规字符必须添加数据源
            row4.lstItem = new List<ListItem>();
            for (var i = 0; i < 20; i++)
            {
                row4.lstItem.Add(new ListItem(i.ToString() + "", i.ToString()));
            }
            my.lstRow.Add(row4);
            return my;
        }
    }
配置文件结构

  2.典型的窗体使用实例

        MyConfig my;
        public frmMain()
        {
            InitializeComponent();
        }

        private void Form3_Load(object sender, EventArgs e)
        {
            my = MyConfig.Load(dataGridView1, "./1.json"); ;
        }

        private void btnAdd_Click(object sender, EventArgs e)
        {
            frmCreate fc = new frmCreate(my);
            if (fc.ShowDialog() == DialogResult.OK)
            {
                my = fc.my;
            }
        }

        private void btnDel_Click(object sender, EventArgs e)
        {
            if (dataGridView1.CurrentCell != null)
            {
                var name = dataGridView1.CurrentRow.Cells["clName"].Value.ToString();
                my.Remove(name);
            }
        }

        private void btnUpdate_Click(object sender, EventArgs e)
        {
            if (dataGridView1.CurrentCell != null)
            {
                var name = dataGridView1.CurrentRow.Cells["clName"].Value.ToString();
                frmCreate fc = new frmCreate(my, name);
                if (fc.ShowDialog() == DialogResult.OK)
                {
                    my = fc.my;
                }
            }
        }
使用实例

  

  

     有些控件列的操作和一些必需的属性设置,把这些代码从Designer.cs中拷贝出来,直接放在方法里直接调用,是为了避免新建一个窗体,又有重复那么多设置操作。但这样肯定会带来一定的不灵活性。

  就这样做了2天,做完发现实用性有限,权当技术研究吧。

  另外还可以配置参数实体上添加正则属性,这样就方便进行正则检查参数是否合法。

上一篇: IBM:在错误的裁员转型路上迷失 下一篇: 没有下一篇了!
发表评论
用户名: 匿名