使用 LINQ (C#) 在 Winforms 中创建数据的主从表示





4.00/5 (18投票s)
使用 LINQ (C#) 在 Winforms 中创建数据的主从表示
引言
在构建企业应用程序时,我们可能需要开发主从事务展示或录入数据表单。
我想在我的 Windows 应用程序中使用 LINQ 的强大功能。本文通过一个简单的例子,展示了如何使用 C# Winforms 和 LINQ 实现主从数据展示。
背景
在我之前的文章中,我使用 Northwind 数据库来处理 LINQ,这里我使用自定义对象来保存数据。 LINQ 用于通过连接和分组从对象源提取数据。
在这个例子中,使用了两个类 Department(部门)和 Employee(员工),并在每个类中声明了必需的公共属性。 每个类都有构造函数来保存数据。
还使用了两个 GridView 来显示 Department 和 Employee 记录。 数据将通过 BindingSource 绑定到 GridView。
BindingSource 类 (System.Windows.Forms)
BindingSource 组件有多种用途。 首先,它通过提供货币管理、更改通知以及 Windows Forms 控件和数据源之间的其他服务,简化了窗体上控件与数据的绑定。 这是通过使用 DataSource 属性将 BindingSource 组件附加到您的数据源来实现的。
最初,数据将被加载到 BindingSource,然后 BindingSource 用于将数据放入 GridView 控件中。
在这种情况下,BindingSource 和 GridView 控件的 DataSource 属性都需要设置。
LINQ 数据将绑定到 Binding Source 的 DataSource 属性,而 BindingSource 用于设置 GridView 的 DataSource 属性。
为两个数据源创建对象列表并添加数据。
private List<Department> Departments = new List<Department>(); private List<Employee> Employees = new List<Employee>();
通过列表向 Department 添加数据。
Departments.Add(new Department(10, "Sales", "Hyderabad"));
通过列表向 Employee 添加数据。
Employees.Add(new Employee(1, "Krishna Prasad", 10, "Manager", 30000));
将 GridView 的 AutoGeneratedColumns 属性设置为 true,以显示来自对象源的 BindingSource 数据。
dgvEmployees.AutoGenerateColumns = true; dgvDepartments.AutoGenerateColumns = true;
可以像下面指定的那样对数据进行分组并从对象源检索。
var matchingEmployees = from dept in Departments join emp in Employees on dept.DeptNo equals emp.DeptNo into AvailableEmployees select new { department = dept, employees = AvailableEmployees };
Dictionary 对象用于保存选定的分组数据。
词典
表示键和值的集合。
Dictionary<(Of <(TKey, TValue>)>) 泛型类提供了从一组键到一组值的映射。 字典的每个添加项都包含一个值及其关联的键。 通过使用其键检索值非常快,接近 O(1),因为 Dictionary<(Of <(TKey, TValue>)>) 类是作为哈希表实现的。
Dictionary 对象需要两个参数,第一个是键,第二个是值。
在这个例子中,Key 是 Department(记录),value 是所选 Department 的相关 Employee 记录。
private Dictionary<Department, IEnumerable<Employee>> GroupEmployee;
this.GroupEmployee = matchingEmployees.ToDictionary(x => x.department, y => y.employees);
现在数据已保存到 Dictionary 对象中。 每当在 master GridView 中更改 Master 记录(例如:此示例中的 Department)的选择时,需要在详细信息 GridView 中显示记录(例如:此示例中的 Employee 记录)。
可以通过 BindingSources 的 CurrentChanged 事件来实现此过程,因为它们绑定到特定数据,并且 GridView 绑定到 BindingSources。
private void bsDepartments_CurrentChanged(object sender, EventArgs e) { bsEmployees.DataSource = this.GroupEmployee [(Department) bsDepartments.Current]; }
使用代码
下载附加的 Zip 文件,重新构建解决方案并运行 SecondLINQ 示例即可。
完整代码
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace SecondLINQ { public partial class Form1 : Form { private List<Department> Departments = new List<Department>(); private List<Employee> Employees = new List<Employee>(); private Dictionary<Department, IEnumerable<Employee>> GroupEmployee; public Form1() { InitializeComponent(); dgvEmployees.AutoGenerateColumns = true; dgvDepartments.AutoGenerateColumns = true; loadDepartments(); loadEmployees(); var matchingEmployees = from dept in Departments join emp in Employees on dept.DeptNo equals emp.DeptNo into AvailableEmployees select new { department = dept, employees = AvailableEmployees }; this.GroupEmployee = matchingEmployees.ToDictionary(x => x.department, y => y.employees); bsDepartments.DataSource = GroupEmployee.Keys; }
public class Department { private int deptNo = 0; private String deptName = String.Empty; private String deptLoc = String.Empty; public Department() { } public Department(int DeptNo, String DeptName, String DeptLoc) { deptNo = DeptNo; deptName = DeptName; deptLoc = DeptLoc; } public int DeptNo { set { deptNo = value; } get {return deptNo;} } public String DeptName { set { deptName = value; } get { return deptName; } } public String DeptLoc { set { deptLoc = value; } get { return deptLoc; } } }
private class Employee { private int employeeNo; private String employeeName; private int deptNo; private String job; private Double salary; public Employee() { } public Employee(int EmployeeNo, String EmployeeName, int DeptNo, String Job, Double Salary) { employeeNo = EmployeeNo; employeeName = EmployeeName; deptNo = DeptNo; job = Job; salary = Salary; } public int EmployeeNo { set { employeeNo = value; } get { return employeeNo; } } public String EmployeeName { set { employeeName = value; } get { return employeeName; } } public int DeptNo { set { deptNo = value; } get { return deptNo; } } public String Job { set { job = value; } get { return job; } } public Double Salary { set { salary = value; } get { return salary; } } } private void loadDepartments() { Departments.Add(new Department(10, "Sales", "Hyderabad")); Departments.Add(new Department(20, "Purchases", "Mumbai")); Departments.Add(new Department(30, "Admin", "Mumbai")); Departments.Add(new Department(40, "Accounts", "Mumbai")); Departments.Add(new Department(50, "Training", "Hyderabad")); Departments.Add(new Department(60, "Stores", "Hyderabad")); } private void loadEmployees() { Employees.Add(new Employee(1, "Krishna Prasad", 10, "Manager", 30000)); Employees.Add(new Employee(2, "Rajesh", 10, "Clerk", 10000)); Employees.Add(new Employee(3, "Ramesh", 10, "Assistant", 5000)); Employees.Add(new Employee(4, "Ragesh", 10, "Computer Operator", 4000)); Employees.Add(new Employee(5, "Murali", 20, "Manager", 30000)); Employees.Add(new Employee(6, "Anil", 20, "Clerk", 10000)); Employees.Add(new Employee(7, "Karthik", 30, "Manager", 30000)); Employees.Add(new Employee(8, "Anirudh", 30, "Assistant", 7000)); Employees.Add(new Employee(9, "Sarma Chada", 40, "Manager", 15000)); Employees.Add(new Employee(10, "Anupama", 40, "Assistant", 3000)); Employees.Add(new Employee(10, "Anirudh", 40, "Accountant", 7000)); Employees.Add(new Employee(11, "Sailesh", 60, "Store Keeper", 4000)); } private void bsDepartments_CurrentChanged(object sender, EventArgs e) { bsEmployees.DataSource = this.GroupEmployee [(Department) bsDepartments.Current]; } } }
关注点
通过 LINQ 连接和分组数据非常容易。 我们可以编写一个简单的 LINQ 表达式(使用 Lambda)来从多个表获取复杂数据。
历史
发布和更新于 2008 年 11 月 7 日