WinForm程序中表单的自动保存列的宽度和位置,是一种常见的功能,对于用户体验来说是非常好的。现记录一下实现过程:
1、新建一个类,命为为:DataGridViewColumnStyle。
这个类实现的功能:当DataGridView的列宽或列的位置发生改变时,系统将自动记录DataGridView的设置。当用户下次打开此窗体的时候,表单的样式是他上次设置的模样。代码如下:
class DataGridViewColumnStyle { private DataGridView dgvTarget = null; //待处理的DataGridView对象 private string path; //文件路径 private DataTable dtColumnStyle = null; //列样式数据表 private bool isBindColumnStyle = false; //是否绑定列样式否 //DataGridView属性 public DataGridView DataGridView { get { return dgvTarget; } set { //去除事件 if (dgvTarget != null) { dgvTarget.ColumnWidthChanged -= new DataGridViewColumnEventHandler(DataGridView_ColumnWidthChanged); dgvTarget.ColumnDisplayIndexChanged -= new DataGridViewColumnEventHandler(DataGridView_ColumnDisplayIndexChanged); } dgvTarget = value; //注册事件 if (dgvTarget != null) { dgvTarget.ColumnWidthChanged += new DataGridViewColumnEventHandler(DataGridView_ColumnWidthChanged); dgvTarget.ColumnDisplayIndexChanged += new DataGridViewColumnEventHandler(DataGridView_ColumnDisplayIndexChanged); } } } //无参构造函数 public DataGridViewColumnStyle() { } //有参构造函数 public DataGridViewColumnStyle(DataGridView dataGridView) : this() { DataGridView = dataGridView; //文件名 string formName = dgvTarget.FindForm().Name; string userId = "Test"; path = Application.StartupPath + @"Accounts" + userId + "\" + formName + "_" + dgvTarget.Name + ".xml"; //列样式数据表 dtColumnStyle = new DataTable(); dtColumnStyle.TableName = dgvTarget.Name; //表名 dtColumnStyle.Columns.Add("Name"); //列名 dtColumnStyle.Columns.Add("Width"); //列宽度 dtColumnStyle.Columns.Add("DisplayIndex"); //显示顺序 //绑定列样式 BindColumnStyle(); } /// <summary> /// 绑定列样式 /// </summary> private void BindColumnStyle() { try { //赋初始值 isBindColumnStyle = true; //如果不存在则保存列样式 if (!File.Exists(path)) { SaveColumnStyle(); } //加载列样式 dtColumnStyle.ReadXml(path); foreach (DataRow row in dtColumnStyle.Rows) { if (dgvTarget.Columns.Contains(row["Name"].ToString().Trim()) && dgvTarget.Columns[row["Name"].ToString().Trim()].Visible == true) { dgvTarget.Columns[row["Name"].ToString().Trim()].Width = int.Parse(row["Width"].ToString().Trim()); dgvTarget.Columns[row["Name"].ToString().Trim()].DisplayIndex = int.Parse(row["DisplayIndex"].ToString().Trim()); } } } catch (Exception ex) { DeleteColumnStyle(); MessageBox.Show(ex.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); } finally { isBindColumnStyle = false; } } /// <summary> /// 列显示位置改变时 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void DataGridView_ColumnDisplayIndexChanged(object sender, DataGridViewColumnEventArgs e) { if (isBindColumnStyle == false) { SaveColumnStyle(); } } /// <summary> /// 列宽度改变时 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void DataGridView_ColumnWidthChanged(object sender, DataGridViewColumnEventArgs e) { if (isBindColumnStyle == false) { SaveColumnStyle(); } } /// <summary> /// 保存列样式 /// </summary> private void SaveColumnStyle() { try { //如果目录不存在则创建 string dir = path.Substring(0, path.LastIndexOf('\')); if (!Directory.Exists(dir)) { Directory.CreateDirectory(dir); } //读取列样式 string[] columnStyle = new string[dgvTarget.Columns.Count]; foreach (DataGridViewColumn col in dgvTarget.Columns) { if (col.Visible == true) { columnStyle[col.DisplayIndex] = col.Name + '|' + col.Width + '|' + col.DisplayIndex; } } int colsCount = columnStyle.Length; //保存列样式 dtColumnStyle.Rows.Clear(); for (int i = 0; i < colsCount; i++) { string[] str = new string[3]; try { DataRow newRow = dtColumnStyle.NewRow(); str = columnStyle.GetValue(i).ToString().Split('|'); newRow["Name"] = str[0]; newRow["Width"] = str[1]; newRow["DisplayIndex"] = str[2]; dtColumnStyle.Rows.Add(newRow); } catch { continue; } } dtColumnStyle.WriteXml(path); } catch (Exception ex) { MessageBox.Show(ex.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); } } /// <summary> /// 删除列样式 /// </summary> private void DeleteColumnStyle() { try { if (File.Exists(path)) { File.Delete(path); } } catch (Exception ex) { MessageBox.Show(ex.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); } } }
2、以上这些,已经实现了全部的功能。下面开始建一个WinForm程序来测试结果,为方便测试将DataGridView的数据源由xml文件读取。
从SQL Server数据库随便找张数据表生成XML,文件保存为Test.xml。(请将Test.xml文件拷贝到Debug文件夹下面)
SELECT TOP 10 MO_NO,MRP_NO,QTY,BIL_NO FROM MF_MO WHERE MO_DD='2019-11-07' ORDER BY MO_NO FOR XML PATH ('Category'),TYPE,ROOT('DocumentElement')
3、新建一个WinForm程序,命名为Main,并拖入一个DataGridView控件,请保留【启用列重新排序】的勾选。
Main_Load方法如下:
private void Main_Load(object sender, EventArgs e) { try { //xml文件路径 string path = @"Test.xml"; //读取文件 DataSet ds = new DataSet(); if (File.Exists(path)) { ds.ReadXml(path); } dataGridView1.DataSource = ds.Tables.Count > 0 ? ds.Tables[0] : null; //加工dataGridView1 #region 加列标题测试 dataGridView1.Columns[0].HeaderText = "制令单号"; dataGridView1.Columns[1].HeaderText = "成品编号"; dataGridView1.Columns[2].HeaderText = "生产数量"; dataGridView1.Columns[3].HeaderText = "来源单号"; #endregion DataGridViewColumnStyle style = new DataGridViewColumnStyle(dataGridView1); } catch (Exception ex) { MessageBox.Show(ex.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); } }
4、执行程序,随意拖动或拉宽DataGridView列,然后重新进一次程序即可看到效果:
好了,分享就到此结束了,希望对有此需要的人有一些帮助。