zoukankan      html  css  js  c++  java
  • Winform 在DataGrid中签入Combo

    背景

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

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

    资源下载

      示例代码

      

      

    实现

      1.设计数据结构。

        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('
    ').Split('
    ');
                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天,做完发现实用性有限,权当技术研究吧。

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

  • 相关阅读:
    实现发送邮件
    c#操作sqlite(包含中文支持)
    C# & SQLite
    卸载impala
    kudu集成impala
    Kudu的卸载(cdh)
    Kudu的集群安装(1.6.0-cdh5.14.0)
    ELK日志平台搭建
    logstash之OutPut插件
    logstash之Filter插件
  • 原文地址:https://www.cnblogs.com/codealone/p/3236302.html
Copyright © 2011-2022 走看看