65.9K
CodeProject 正在变化。 阅读更多。
Home

用于域对象的网格

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.25/5 (5投票s)

2008年5月18日

CPOL

4分钟阅读

viewsIcon

38587

downloadIcon

291

一个实用的领域对象网格,用于 WinForms 系统。

引言

使用 Windows Forms 应用程序的一个优点是可以直接将领域对象包含到 UI 组件中,例如在下拉列表和列表框中。在 UI 组件中,表格网格非常有用,因为它们从信息角度提供了广泛的视图,并且在 CRUD 窗口中被广泛使用。

假设需要构建一个包含一些相关信息的类别网格系统。已经有一个 `Category` 类,它被声明为一个 POCO 类,具有以下 C# 代码:

using System;

namespace DomainObjects
{
    public class Category
    {
        private long _id;
        public virtual long Id
        {
            get { return this._id; }
            set { this._id = value; }
        }

        private string _categoryName;
        public virtual string CategoryName
        {
            get { return this._categoryName; }
            set { this._categoryName = value; }
        }

        private string _description;
        public virtual void SetDescription(string description)
        {
            this._description = description;
        }
        public virtual string GetDescription()
        {
            return this._description;
        }       
    }
}

为此,在 .NET 框架中,我们可以找到 `DataGrid`。为了在 `DataGrid` 中显示对象数据,`DataSource` 属性必须接收这些对象的集合。

IList<category> lstCategories = PopulateCategoriesList(lstCategories);
this.dataGridView1.DataSource = lstCategories;

作为 Categories 列表的结果,得到了以下网格:

A_Grid_for_Domain_Objects_html_m12abf3ee.gif

请注意,`DataGrid` 组件只能看到 `Id` 和 `CategoryName` 属性,并将它们的内容显示为列。

当与对象集合一起使用时,`DataGrid` 会出现以下缺点:

  • 它在反射映射方面非常受限,因为它只能将公共属性视为网格中的列,这使得它在多种对象场景中无法使用;
  • 配置诸如标题和宽度之类的列功能不是一项直观的任务;
  • 无法遍历对象关联以显示更深层次的另一个对象的数据;

为了克服这些缺点,本文提出了一种用于领域对象的网格,该网格能够将字段和对象之间的关联映射到网格表中的列,称为 `ObjectGrid`。

示例用法

要使用 `ObjectListGrid`,首先,您应该将组件拖到您的窗口上,并将其重命名为 `gridResults`。将上面的网格替换为名为 `gridResults` 的 `ObjectGrid` 后,必须在接收对象项之前对其进行配置。

// Domain Grid Mappings for Category Class ( or any class with the members below ) 
this.gridResults.AddColumn(new string[] {"CategoryName"},"Name",80);      
this.gridResults.AddColumn(new string[] {"GetDescription"}, "Description", 200);
// Domain Grid receives collection of Categories as a Datasource
this.gridResults.DataSource = PopulateCategoriesList();

下面是生成的网格:

A_Grid_for_Domain_Objects_html_m49dd997a.gif

将对象图转换为网格表

`ObjectGrid` 是一个 .NET 用户组件,它包装了一个 `DataGrid`。它具有描述列特性的方法,并且必须接收一个对象集合作为 DataSource。

这些列通过一系列成员名称映射为值,组件使用这些成员名称遍历对象图,从集合中的对象开始,通过反射获取链中最终对象的特定数据。

A_Grid_for_Domain_Objects_html_5f2c87a3.gif

由于它使用成员名称的反射信息,因此同一个 `ObjectGrid` 可以用来显示不同类型的对象,前提是它们包含这些成员的名称。

另一种用法

例如,考虑下面的 UML 中的供应商网格:

A_Grid_for_Domain_Objects_html_m2cd7c8a6.jpg

在这个网格中,需要显示供应商的以下数据:公司名称、电话、街道、城市、州和国家。

在 Windows Forms 应用程序中使用此组件需要四个步骤:

  1. 将组件拖到 Windows 窗体上的所需位置。
  2. A_Grid_for_Domain_Objects_html_6892aa91.gif

  3. 添加描述标题、长度和对象成员的列。
  4. this.gridResults.AddColumn(new string[]{"CompanyName"},"Name",80);
    this.gridResults.AddColumn(new string[]{"ContactName"},"Contact",90);
    this.gridResults.AddColumn(new string[]{"Phone"},"Phone",50);
    this.gridResults.AddColumn(new string[]{"HomePage"},"Home Page",110);
    this.gridResults.AddColumn(new string[]{"Street","Name"},"Street",50);
    this.gridResults.AddColumn(new string[]{"Street","City","Name"},"City",50);
    this.gridResults.AddColumn(new string[]{"Street","City","State","Name"},"State", 50);
    this.gridResults.AddColumn(new string[]{"Street","City", "State","Country", 
                               "Name"},"Country",50);

    如果您知道此网格仅用于供应商,则可以在窗体初始化时将列添加到网格中。

    第一个参数是成员名称数组(可以是方法、属性或字段)。第二个是列标题,第三个是列宽度。第一个参数也是此网格的关键方面。`map` 方法负责通过在内存中导航领域网格列来映射它们。

    例如,为了获取供应商的城市名称,需要执行 `supplier.Street.City.Name`。因此,`Street` 列映射为 {“Street”, “City”, “Name”}。

    理论上,`ObjectGrid` 能够导航 N 级对象关联,为避免此组件出现异常的唯一要求是对象必须实现映射的成员名称,并且成员返回值实现前向成员名称,依此类推。

  5. 将对象集合设置到组件中。每个对象都必须实现映射的成员。
  6. this.olstgResults.DataSource = PopulateSuppliersList();

向网格添加、更新和删除对象

为了修改网格显示的数据,可以通过 `Item` 属性向网格添加或删除新对象。

// Adding new element to the grid
this.gridResults.Items.Add(category); 
           
// Removing element from the grid
this.gridResults.Items.Remove(category);

当列表中的对象被更改时,必须使用 `UpdateView` 方法通知网格。

// Refreshing grid
category.SetDescription("New description");
this.gridResults.Refresh();

恢复选定对象

除了易于配置以查看数据外,使用 `ObjectGrid` 的另一个优点是可以将代表选定行的对象恢复到应用程序中。

选择网格行后,例如:

A_Grid_for_Domain_Objects_html_5a89fa18.gif

可以使用 `CurrentObject` 属性恢复选定对象:

object selectedObject = this.gridResults.CurrentObject;
© . All rights reserved.