本文主要介绍如何在DataGridView的基础上,自定义DataGridView,实现列的顺序、宽度、显示名等信息的保存与读取,实现用户的个性化需求。
文章目录
1. 需求说明2. 实现3. 使用方式参考资料1. 需求说明
虽说在文章简介中大致说明了要实现的功能是什么,但是这里还是举个例子说明一下:
假设现有一张学生表,表头如下:
每个用户对于每张表的关注点不同,假设我比较关注学校和年级这些信息,那么我想要把学校和年级放在姓名的前面(如果一些表很复杂,列很多,学校和年级导致在后面,需要拉动滑动条才能看见,这是很麻烦的):
如果我退出系统后,下一次再打开系统,发现学校和年级又跑到后面去了,不得不再次拖动相关的列,这对于用户来说是一件很麻烦的事。
所以,我们需要保存DataGridView中的列信息,使得用户下次打开系统时,列的顺序仍然和上次退出时的一样:
这就是本文要介绍的内容。
2. 实现
主要新建一个组件类,然后将父类Component
改为DataGridView
,MyDataGridView.cs
部分代码如下:
public partial class MyDataGridView : DataGridView{private DataTable dataTable; //列样式数据表private string path; //XML文件路径public MyDataGridView(){InitializeComponent();}public MyDataGridView(IContainer container){container.Add(this);InitializeComponent();}public void InitAfterConstructor(){ path = Application.StartupPath + @"\User\" + this.Name + ".xml";//列样式数据表dataTable = new DataTable();dataTable.TableName = this.Name; //表名dataTable.Columns.Add("Name"); // 列名dataTable.Columns.Add("HeaderText"); // 显示的名字dataTable.Columns.Add("DisplayIndex"); // 显示顺序dataTable.Columns.Add("Width"); // 列宽度dataTable.Columns.Add("DataPropertyName"); // 绑定的数据项名dataTable.Columns.Add("Visible"); // 是否可见// 加载列样式BindColumnStyle();}/// <summary>/// 绑定列样式/// </summary>private void BindColumnStyle(){try{//如果不存在则保存列样式if (!File.Exists(path)){SaveColumnStyle();return;}//加载列样式dataTable.ReadXml(path);foreach (DataRow row in dataTable.Rows){if (Columns.Contains(row["Name"].ToString().Trim())){Columns[row["Name"].ToString()].HeaderText = row["HeaderText"].ToString();Columns[row["Name"].ToString()].DisplayIndex =int.Parse(row["DisplayIndex"].ToString());Columns[row["Name"].ToString()].Width = int.Parse(row["Width"].ToString());Columns[row["Name"].ToString()].DataPropertyName =row["DataPropertyName"].ToString();Columns[row["Name"].ToString()].Visible = bool.Parse(row["Visible"].ToString());}}}catch (Exception ex){Console.WriteLine(ex.Message);}}/// <summary>/// 保存列样式/// </summary>private void SaveColumnStyle(){try{//如果目录不存在则创建var dir = path.Substring(0, path.LastIndexOf('\\'));if (!Directory.Exists(dir)) Directory.CreateDirectory(dir);//读取列样式dataTable.Rows.Clear();foreach (DataGridViewColumn column in this.Columns){var newRow = dataTable.NewRow();newRow["Name"] = column.Name;newRow["HeaderText"] = column.HeaderText;newRow["DisplayIndex"] = column.DisplayIndex;newRow["Width"] = column.Width;newRow["DataPropertyName"] = column.DataPropertyName;newRow["Visible"] = column.Visible;dataTable.Rows.Add(newRow);}// 保存列样式到XML文件中dataTable.WriteXml(path);}catch (Exception ex){Console.WriteLine(ex.Message);}}}
MyDataGridView.designer.cs
部分的代码如下,最主要的是在Dispose()
方法中添加保存列样式的方法,注意顺序:
partial class MyDataGridView{....../// <summary> /// 清理所有正在使用的资源。/// </summary>/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>protected override void Dispose(bool disposing){// 关闭保存列样式,注意要先保存列样式,再调用父类的Dispose()SaveColumnStyle();if (disposing && (components != null)){components.Dispose();}base.Dispose(disposing);}......}
3. 使用方式
当编写好自定义的DataGridView后,编译一下项目,这样我们就可以在工具箱中看到自定义的控件了。
然后新建一个界面Form,将自定义的MyDataGridView
拖进界面,并设置启用列重新排序,然后添加三列:
在Form的构造方法中添加MyDataGridView
的初始化方法(注意:该步骤需要手动添加!):
public partial class Form1 : Form{public Form1(){InitializeComponent();myDataGridView1.InitAfterConstructor();}}
启动项目,改变列的排序,页面如下:
然后关闭页面,再次启动项目,列顺序如之前的一样。
在项目的xxx\bin\Debug\User
下,有XML文件记录着列的排序、宽度等信息:
<?xml version="1.0" standalone="yes"?><DocumentElement><myDataGridView1><Name>Column1</Name><HeaderText>Column1</HeaderText><DisplayIndex>2</DisplayIndex><Width>72</Width><DataPropertyName /><Visible>True</Visible></myDataGridView1><myDataGridView1><Name>Column2</Name><HeaderText>Column2</HeaderText><DisplayIndex>0</DisplayIndex><Width>72</Width><DataPropertyName /><Visible>True</Visible></myDataGridView1><myDataGridView1><Name>Column3</Name><HeaderText>Column3</HeaderText><DisplayIndex>1</DisplayIndex><Width>72</Width><DataPropertyName /><Visible>True</Visible></myDataGridView1></DocumentElement>
整个自定义的MyDataGridView
逻辑如下:
在父页面(Form)加载完控件后,调用InitAfterConstructor()
方法,加载之前保存的列顺序、宽度等信息;在页面关闭时,保存列顺序、宽度等信息;
参考资料
[1] /atomy/p/11852072.html