























在实际应用开发中,我们常常需要向用户展示数据,而数据的呈现方式通常以二维表格,折线图,柱状图等图表为主,最常见的就是表格,如销售的统计报表,明细列表等。今天我们以一些简单的小例子,简述在基于.NET的Windows窗体编程中数据表格的应用,仅供学习分享使用,如有不足之处,还请指正。

在WinForms开发中,数据表格控件为DataGridView,它提供了一种强大且灵活的方法来显示表格格式数据。使用DataGridView控件,可以显示和编辑来自多种不同类型的数据源的表格数据,同时DataGridView 控件高度可配置且可扩展,它提供许多属性、方法和事件来自定义其外观和行为。建议在 Windows 窗体应用程序中显示表格数据时,优先使用 DataGridView 控件,而不是使用其他控件(例如,DataGrid)。
将数据绑定到 DataGridView 控件非常简单,只需要设置 DataSource 属性即可,如果绑定的数据源包含多个列表或表,则需要将 DataMember 属性设置为指定要绑定到的列表或表的名称。DataGridView 控件支持标准 Windows 窗体数据绑定模型,它可以绑定到以下数据类型列表:
通常,将DataGridView绑定到 BindingSource 组件,并将 BindingSource 组件绑定到另一个数据源,或者使用业务对象填充BindingSource 。BindingSource 组件是首选数据源,它可以绑定到各种数据源,并且可以自动解决许多数据绑定问题。那什么是BindingSource呢?
BindingSource,它封装一个数据源以便绑定到控件,此组件有两个用途:
下图展示了 BindingSource 组件在现有数据绑定架构中的角色和位置。

同时对于需要导航窗体上数据的用户,BindingNavigator 组件使你能够与 BindingSource 组件协调导航和作数据。
DataGridView关键属性,主要有以下几个:
在Visual Studio设计器中,选中DataGridView控件,然后点击右侧的箭头,在弹出的“DataGridView任务”菜单中,可以点击“添加列...”或“编辑列...”,建议点击“编辑列...”,因为在弹出的“编辑列”窗口中,即可以添加列,也可以编辑现有列。如下图所示:

在“编辑列”窗口中,可以设置添加列,或编辑现有列,DataGridView控件的数据列,主要有以下常用属性:
注意:DataGridView默认会勾选“启用添加”,“启用编辑”,“启用删除”等功能,如果不需要,可以在点击“右箭头”弹出的“DataGridView任务”菜单中取消其功能。
接下来主要以一个实际案例,简述DataGridView控件的相关用法。
通过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>
/// 是否OK,true:是 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 List<Student> students;
/// <summary>
/// 构造函数
/// </summary>
public SqlDataHelper()
{
InitDataInfo();
}
/// <summary>
/// 使用列表,模拟数据库数据,假定数据库中有20名学生信息
/// </summary>
private void InitDataInfo()
{
students = new List<Student>();
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 name="name"></param>
/// <returns></returns>
public List<Student> 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 name="id"></param>
/// <returns></returns>
public Student? Get(int id)
{
return students.FirstOrDefault(item => item.Id == id);
}
/// <summary>
/// 添加学生
/// </summary>
/// <param name="name"></param>
/// <param name="age"></param>
/// <param name="gender"></param>
/// <param name="isoker"></param>
/// <param name="birthdate"></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 name="id"></param>
public void Delete(int id)
{
var student = students.FirstOrDefault(item => item.Id == id);
if (student != null)
{
this.students.Remove(student);
}
}
/// <summary>
/// 编辑学生
/// </summary>
/// <param name="id"></param>
/// <param name="name"></param>
/// <param name="age"></param>
/// <param name="gender"></param>
/// <param name="isoker"></param>
/// <param name="birthdate"></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;
}
}
}
}
在本实例中,通过两个SplitContainer布局容器控件实现上,中,下布局结构:
设置步骤:
具体如下所示:

在Form表单的类文件中,启动页面加载数据需要以下步骤:
核心代码如下:
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)
{
List<Student> students = sqlDataHelper.Query(string.Empty);
this.bdsData.DataSource = students;
}
private void btnQuery_Click(object sender, EventArgs e)
{
string name = this.txtName.Text.Trim();
List<Student> students = sqlDataHelper.Query(name);
this.bdsData.DataSource = students;
}
}
}
增加BindingNavigator,由于BindingNavigator并不在工具箱中出现,无法通过设计器拖动到Form表单中,但可以通过后台代码添加。本实例将BindingNavigator控件添加到UI布局的最底层部分。如下所示:
private void FrmData_Load(object sender, EventArgs e)
{
List<Student> 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个问题。
首先打开“编辑列”对话框,然后选择BirthDate列,在右侧的属性框中,选择DefaultCellStyle,然后点击右侧的“...”按钮,打开“CellStyle生成器”如下所示:

在“CellStyle生成器”中,选择Format,点击右侧的“...”按钮,打开“格式化字符串”对话框,如下所示:

在“格式化字符串”对话框,选择日期,可以选择需要显示的格式,如:“yyyy/MM/dd”。

也可以自定义格式,本示例自定义格式为“yyyy-MM-dd”,如下所示:

设置格式后,BirthDate显示内容如下所示:

也可通过后台代码进行设置,如在Form的Load事件中设置默认单元格样式,如下所示:
this.dgvColumnBirchDate.DefaultCellStyle.Format = "yyyy-MM-dd";
为了将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数据表格》的全部内容,旨在抛砖引玉,希望可以一起学习,共同进步。
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。