基于.NET的Windows窗体编程之WinForms数据表格
在实际应用开发中我们常常需要向用户展示数据而数据的呈现方式通常以二维表格折线图柱状图等图表为主最常见的就是表格如销售的统计报表明细列表等。今天我们以一些简单的小例子简述在基于.NET的Windows窗体编程中数据表格的应用仅供学习分享使用如有不足之处还请指正。概述在WinForms开发中数据表格控件为DataGridView它提供了一种强大且灵活的方法来显示表格格式数据。使用DataGridView控件可以显示和编辑来自多种不同类型的数据源的表格数据同时DataGridView 控件高度可配置且可扩展它提供许多属性、方法和事件来自定义其外观和行为。建议在 Windows 窗体应用程序中显示表格数据时优先使用 DataGridView 控件而不是使用其他控件例如DataGrid。将数据绑定到 DataGridView 控件非常简单只需要设置 DataSource 属性即可如果绑定的数据源包含多个列表或表则需要将 DataMember 属性设置为指定要绑定到的列表或表的名称。DataGridView 控件支持标准 Windows 窗体数据绑定模型它可以绑定到以下数据类型列表实现 IList 接口的任何类包括一维数组。实现 IListSource 接口的任何类例如 DataTable 和 DataSet 类。实现 IBindingList 接口的任何类如 BindingListT 类。实现 IBindingListView 接口的任何类如 BindingSource 类。通常将DataGridView绑定到 BindingSource 组件并将 BindingSource 组件绑定到另一个数据源或者使用业务对象填充BindingSource 。BindingSource 组件是首选数据源它可以绑定到各种数据源并且可以自动解决许多数据绑定问题。那什么是BindingSource呢BindingSourceBindingSource它封装一个数据源以便绑定到控件此组件有两个用途将一个窗体的DataGridView控件绑定到数据时该组件会提供一个间接层。 要实现此目标可以先将 BindingSource 组件绑定到你的数据源然后再将窗体上的控件绑定到 BindingSource 组件。 与数据的所有进一步交互包括导航、排序、筛选和更新都是通过调用 BindingSource 组件来完成的。BindingSource 组件可以充当强类型的数据源。 使用 BindingSource 方法将类型添加到 Add 组件将创建该类型的列表。下图展示了 BindingSource 组件在现有数据绑定架构中的角色和位置。同时对于需要导航窗体上数据的用户BindingNavigator 组件使你能够与 BindingSource 组件协调导航和作数据。关键属性DataGridView关键属性主要有以下几个NameDataGridView控件在Form表单中的唯一标识。Dock定义空间的停靠方式主要有NoneTopBottomLeftRightFill等几种方式默认为None(不停靠)通过Location定义控件在父容器中的位置。ColumnsDataGridView控件的列属性点击它可以打开“编辑列”对话框。DataMember如果绑定的数据源有多个子表时可以通过DataMember属性指定需要绑定的数据表。MultiSelect标识是否可以一次选择多个单元格或行或列。DataSource表示DataGridView控件绑定的数据源。AutoGenerateColumns 是否根据数据源中的数据自动生成列默认为true。添加或编辑列在Visual Studio设计器中选中DataGridView控件然后点击右侧的箭头在弹出的“DataGridView任务”菜单中可以点击“添加列...”或“编辑列...”建议点击“编辑列...”因为在弹出的“编辑列”窗口中即可以添加列也可以编辑现有列。如下图所示在“编辑列”窗口中可以设置添加列或编辑现有列DataGridView控件的数据列主要有以下常用属性Name指定数据列的唯一标识它在Form表单或UserControl中具有唯一性。ColumnType指定数据列的类型表示数据将以何种形式呈现它具有几种选择DataGridViewTextBoxColumn文本的形式展示数据DataGridViewImageColumn列数据可以展示图片DataGridViewCheckBoxColumn复选框的形式展示数据DataGridViewComoboBoxColumn下拉框的形式展示数据DataGridViewButtonColumn按钮的形式展示数据DataGridViewLinkColumn超链接的形式展示数据。DataPropertyName指定数据列绑定到数据源的列名称用于标识显示数据源的哪一列。HeaderText列标题表示列标题单元格的文本内容。Visible指定列是否可见true显示数据列false隐藏数据列。ReadOnly指定用户是否可以编辑列true不可编辑false可编辑。Frozen是否冻结列水平滚动条移动时列是否移动。Width列的宽度MinimumWidth列的最小宽度。注意DataGridView默认会勾选“启用添加”“启用编辑”“启用删除”等功能如果不需要可以在点击“右箭头”弹出的“DataGridView任务”菜单中取消其功能。DataGridView实例接下来以一个实际案例简述DataGridView控件的相关用法。1. 构建数据源通过BindingSource组件数据源的支持所有IEnumerable 接口的实现今天以学生列表为例首先创建Student模型类定于学生包含 的具体属性如下所示namespace Okcoder.WinForm.Demo { /// summary /// 学生信息 /// /summary public class Student { /// summary /// 唯一标识 /// /summary public int Id { get; set; } /// summary /// 姓名 /// /summary public string Name { get; set; } /// summary /// 年龄 /// /summary public int Age { get; set; } /// summary /// 性别 true:男 false:女 /// /summary public bool Gender { get; set; } /// summary /// 是否OKtrue:是 false:否 /// /summary public bool IsOker { get; set; } /// summary /// 出生日期 /// /summary public DateTime BirthDate { get; set; } } }创建SqlDataHelper类用于构建数据源模拟从数据库中获取数据。具体如下所示using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Okcoder.WinForm.Demo { /// summary /// 数据帮助类 /// /summary public class SqlDataHelper { private ListStudent students; /// summary /// 构造函数 /// /summary public SqlDataHelper() { InitDataInfo(); } /// summary /// 使用列表模拟数据库数据假定数据库中有20名学生信息 /// /summary private void InitDataInfo() { students new ListStudent(); students.Add(new Student() { Id 1, Name 张三丰, Age 100, Gender true, IsOker true, BirthDate DateTime.Now.AddYears(-100) }); students.Add(new Student() { Id 2, Name 宋远桥, Age 50, Gender true, IsOker true, BirthDate DateTime.Now.AddYears(-50) }); students.Add(new Student() { Id 3, Name 俞莲舟, Age 48, Gender true, IsOker true, BirthDate DateTime.Now.AddYears(-48) }); students.Add(new Student() { Id 4, Name 俞岱岩, Age 46, Gender true, IsOker true, BirthDate DateTime.Now.AddYears(-46) }); students.Add(new Student() { Id 5, Name 张松溪, Age 44, Gender true, IsOker true, BirthDate DateTime.Now.AddYears(-44) }); students.Add(new Student() { Id 6, Name 张翠山, Age 45, Gender true, IsOker true, BirthDate DateTime.Now.AddYears(-45) }); students.Add(new Student() { Id 7, Name 殷梨亭, Age 43, Gender true, IsOker true, BirthDate DateTime.Now.AddYears(-43) }); students.Add(new Student() { Id 8, Name 莫声谷, Age 42, Gender true, IsOker true, BirthDate DateTime.Now.AddYears(-42) }); students.Add(new Student() { Id 9, Name 宋青书, Age 20, Gender true, IsOker false, BirthDate DateTime.Now.AddYears(-20) }); students.Add(new Student() { Id 10, Name 张无忌, Age 18, Gender true, IsOker true, BirthDate DateTime.Now.AddYears(18) }); students.Add(new Student() { Id 11, Name 郭襄, Age 100, Gender true, IsOker true, BirthDate DateTime.Now.AddYears(-100) }); students.Add(new Student() { Id 12, Name 灭绝师太, Age 51, Gender false, IsOker true, BirthDate DateTime.Now.AddYears(-51) }); students.Add(new Student() { Id 13, Name 周芷若, Age 18, Gender false, IsOker true, BirthDate DateTime.Now.AddYears(-18) }); students.Add(new Student() { Id 14, Name 定敏君, Age 19, Gender false, IsOker false, BirthDate DateTime.Now.AddYears(-19) }); students.Add(new Student() { Id 15, Name 纪晓芙, Age 43, Gender false, IsOker true, BirthDate DateTime.Now.AddYears(-43) }); students.Add(new Student() { Id 16, Name 静玄, Age 30, Gender false, IsOker true, BirthDate DateTime.Now.AddYears(-30) }); students.Add(new Student() { Id 17, Name 静虚, Age 29, Gender false, IsOker true, BirthDate DateTime.Now.AddYears(-29) }); students.Add(new Student() { Id 18, Name 静空, Age 28, Gender false, IsOker true, BirthDate DateTime.Now.AddYears(-28) }); students.Add(new Student() { Id 19, Name 静慧, Age 27, Gender false, IsOker true, BirthDate DateTime.Now.AddYears(-27) }); students.Add(new Student() { Id 20, Name 静迦, Age 26, Gender false, IsOker true, BirthDate DateTime.Now.AddYears(-26) }); } /// summary /// 查询学生列表 /// /summary /// param namename/param /// returns/returns public ListStudent Query(string name) { if (string.IsNullOrEmpty(name)) { return this.students; } var list this.students.Where(item item.Name.Contains(name)).ToList(); return list; } /// summary /// 根据ID获取学生信息 /// /summary /// param nameid/param /// returns/returns public Student? Get(int id) { return students.FirstOrDefault(item item.Id id); } /// summary /// 添加学生 /// /summary /// param namename/param /// param nameage/param /// param namegender/param /// param nameisoker/param /// param namebirthdate/param public void Add(string name,int age,bool gender,bool isoker,DateTime birthdate) { if (students.Count(item item.Name name) 1) { int id students.Count 0 ? students.Max(item item.Id) 1 : 1; students.Add(new Student() { Id id, Name name, Age age, Gender gender, IsOker isoker, BirthDate birthdate }); } } /// summary /// 删除学生 /// /summary /// param nameid/param public void Delete(int id) { var student students.FirstOrDefault(item item.Id id); if (student ! null) { this.students.Remove(student); } } /// summary /// 编辑学生 /// /summary /// param nameid/param /// param namename/param /// param nameage/param /// param namegender/param /// param nameisoker/param /// param namebirthdate/param public void Edit(int id, string name, int age, bool gender, bool isoker, DateTime birthdate) { var student students.FirstOrDefault(item item.Id id); if (student ! null) { student.Name name; student.Age age; student.Gender gender; student.IsOker isoker; student.BirthDate birthdate; } } } }2. UI布局在本实例中通过两个SplitContainer布局容器控件实现上中下布局结构上边为查询条件按钮等功能实现数据列表的搜索。中间为数据区主要存放DataGridView控件显示学生列表数据。底部为导航区主要放置BingNavigator控件。设置步骤拖动DataGridView控件到数据区且设置DataGridView控件的Dock属性为Fill实现自动填充并设置Name属性为dgvData。拖动BindingSource组件到Form表单由于BindingSource作为数据中间层并没有UI呈现所以在Form设计器的最底层设置Name属性为bdsData。将DataGridView的DataSource属性设置为上面的BindingSource组件通过指定名称bdsData进行关联。设置DataGridView需要显示的列根据Student属性为DataGridView添加需要显示的列并设置对应的DataPropertyName属性。具体如下所示3. 加载数据在Form表单的类文件中启动页面加载数据需要以下步骤初始化SqlDataHelper实例对象Form表单的Load事件方法中获取学生信息列表并赋值给BindingSource组件的DataSource属性。在Query按钮的事件处理方法中根据用户输入的检索条件进行查询将获取的列表重新Binding到BindingSource的DataSource属性中即可实现重新赋值。核心代码如下namespace Okcoder.WinForm.Demo { public partial class FrmData : Form { private SqlDataHelper sqlDataHelper; public FrmData() { InitializeComponent(); sqlDataHelper new SqlDataHelper(); } private void FrmData_Load(object sender, EventArgs e) { ListStudent students sqlDataHelper.Query(string.Empty); this.bdsData.DataSource students; } private void btnQuery_Click(object sender, EventArgs e) { string name this.txtName.Text.Trim(); ListStudent students sqlDataHelper.Query(name); this.bdsData.DataSource students; } } }增加BindingNavigator由于BindingNavigator并不在工具箱中出现无法通过设计器拖动到Form表单中但可以通过后台代码添加。本实例将BindingNavigator控件添加到UI布局的最底层部分。如下所示private void FrmData_Load(object sender, EventArgs e) { ListStudent students sqlDataHelper.Query(string.Empty); this.bdsData.DataSource students; //添加BindingNavigator BindingNavigator bdNav new BindingNavigator(true); bdNav.BindingSource bdsData; // 需先创建 BindingSource bdNav.Dock DockStyle.Top; this.splitContainer2.Panel2.Controls.Add(bdNav); }4. 运行示例运行实例效果如下所示在上述示例中还存在4个问题Gender是性别希望看到男女而不是TrueFalse。IsOker是否正派人士希望看到是否而不是TrueFalse。BirthDate是出生日期希望看到年月日即可不需要看到时分秒。DataGridView数据表格中每一行的背景颜色都相同我们希望交替使用不同的背景色。接下来将分别解决这4个问题。日期格式首先打开“编辑列”对话框然后选择BirthDate列在右侧的属性框中选择DefaultCellStyle然后点击右侧的“...”按钮打开“CellStyle生成器”如下所示在“CellStyle生成器”中选择Format点击右侧的“...”按钮打开“格式化字符串”对话框如下所示在“格式化字符串”对话框选择日期可以选择需要显示的格式如“yyyy/MM/dd”。也可以自定义格式本示例自定义格式为“yyyy-MM-dd”如下所示设置格式后BirthDate显示内容如下所示也可通过后台代码进行设置如在Form的Load事件中设置默认单元格样式如下所示this.dgvColumnBirchDate.DefaultCellStyle.Format yyyy-MM-dd;bool类型为了将bool类型的值显示为更加语义化的文本可以订阅DataGridView控件的CellFormatting事件。首先选择DataGridView控件在右侧的属性窗口中点击(⚡️)切换到事件Tab页然后找到CellFormatting事件在右侧的框中双击即可为DataGridView控件添加相应事件。 如下所示在生成的dgvData_CellFormatting事件中根据bool的值重新为单元格赋值如下所示private void dgvData_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e) { if (e.ColumnIndex 3) { //Gender if (e.Value ! null ((bool)e.Value)) { e.Value 男; } else { e.Value 女; } } if (e.ColumnIndex 4) { //IsOker if (e.Value ! null ((bool)e.Value)) { e.Value 是; } else { e.Value 否; } } }格式化后数据显示如下所示行交替样式表格数据通常以类似账本的格式向用户呈现其中交替行具有不同的背景色也是常用功能之一。通过这种格式用户可以更轻松地识别每行中的单元格特别是在有很多列的宽表格中。首先选择DataGridView然后在属性对话框中选择RowDefaultCellStyle在点击右侧的“...”按钮弹出“CellStyle生成器”在其中设置BackColor属性如下所示接着以同样方式设置AlternatingRowsDefaultCellStyle属性中对应的BackColor属性如下所示设置交替背景色后效果如下所示上述交替行设置背景色效果也可以在Form表单的Load事件中添加如下代码dgvData.RowsDefaultCellStyle.BackColor Color.FromArgb(255, 192, 192); dgvData.AlternatingRowsDefaultCellStyle.BackColor Color.FromArgb(192, 255, 255);以上就是《基于.NET的Windows窗体编程之WinForms数据表格》的全部内容旨在抛砖引玉希望可以一起学习共同进步。