WinForms 数据绑定和外键关系
Posted
技术标签:
【中文标题】WinForms 数据绑定和外键关系【英文标题】:WinForms databinding and foreign key relationships 【发布时间】:2010-09-06 23:27:23 【问题描述】:我正在开发一个 WinForms 应用程序(.Net 3.5,无 WPF),我希望能够在数据绑定 DataGridView 中显示外键查找。
这种关系的一个例子是我有一个 OrderLines 表。 Orderlines 与 Products 具有外键关系,而 Products 又与 ProductTypes 具有外键关系。
我想要一个数据绑定的 DataGridView,其中每一行代表一个订单行,显示该行的产品和产品类型。
用户可以直接向网格添加或编辑订单行,并从组合框列中为订单行选择产品 - 这应该会更新 producttype 列,在同一行中显示所选产品的 producttype。
到目前为止,我发现的最合适的方法是引入一个表示订单线的域对象,然后将 DataGridView 绑定到这些订单线的集合。然后,我将属性添加到暴露产品和产品类型的订单线对象,并引发相关的 notifypropertychanged 事件以使所有内容保持最新。然后,在我的 orderline 存储库中,我可以连接这个 orderline 对象和我数据库中的三个表之间的映射。
这适用于数据绑定方面,但必须在存储库中手动编写所有 OR 映射的代码似乎很糟糕。我认为 nHibernate 将能够帮助进行这种接线,但我正在努力通过所有外键进行映射 - 它们似乎工作正常(订单行产品的外键查找基于外键创建正确的产品对象)直到我尝试进行数据绑定,我无法获取数据绑定的 id 列来更新我的产品或产品类型对象。
我的一般方法是否正确?如果是,什么是映射问题的好解决方案?
或者,是否有更好的数据绑定行解决方案,包括我什至没有考虑过的外键查找?
【问题讨论】:
【参考方案1】:我认为您遇到的问题是,当您绑定到网格时,仅支持 INotifyPropertyChanged 是不够的,但是您必须在 IBindingList 实现中触发 ListChanged 事件并确保您覆盖并为 SupportsChangeNotification 属性返回 true。如果您不为此返回 true,则网格不会查找它以了解数据是否已更改。
在 .NET 2.0+ 中,您可以使用 BindingList 类创建一个通用集合,这将解决大部分问题(只是不要忘记为 SupportsChangeNotification 属性覆盖并返回 true)。
如果您用于数据绑定的类具有一个集合属性(例如 IBindingList 或 BindingList),那么您可以将外键网格直接绑定到该属性。在表单设计器中配置绑定时,只需选择集合属性作为网格的数据源。它应该“正常工作”。唯一偷偷摸摸的部分是确保您以正确的方式处理空或空集合。
【讨论】:
感谢 Garo - 这很好地涵盖了我自己的发现。唯一的区别是我有一个外键列,而不是一个网格。我也将更新我赢得的回复,明确导致我出现问题的原因 - 我认为我最初误诊问题的原因可能有用【参考方案2】:欢迎来到 *** :)
通常你会做的是将下拉列表中的信息基于两个值ValueMember and DisplayMember。
ValueMember 是实际控件值的来源(这将是订单行中的键值),显示成员是显示给用户的值而不是值(这将是 FK 值) .
没有什么特别的原因不能只返回所有需要的数据并设置这些属性吗?
【讨论】:
【参考方案3】:这是一个很好的“我如何”视频,演示了数据绑定:
http://windowsclient.net/learn/video.aspx?v=52579
【讨论】:
【参考方案4】:好吧,我不知道 DataGridView 是否支持它,但是当您执行常规 WinForms 数据绑定(例如,到常规 TextBox)时,您可以使用 属性路径 来浏览对象关系。
类似这样的:
myTextBox.DataBindings.Add("Text", anOrderLine, "OrderedPart.PartNumber");
如果这也适用于您的情况,值得一看。
【讨论】:
【参考方案5】:我最初的问题显然不清楚,对此感到抱歉。
问题一般不在于 DataGridView 的数据绑定,也不在于 DataGridViewComboBoxColumn 的实现——正如回答正确的人所说,这在网络上有很好的记录。
我一直试图解决的问题是刷新通过关系向下钻取的属性。
在我的订单示例中,当我更改“产品”列的值时,“产品类型”列未更新 - 即使在代码中我正在设置属性并触发 NotifyPropertyChanged 事件。 (在调试中,我去了所有正确的地方)
经过大量探索后,我意识到当我直接设置数据源的“产品类型”属性时,这甚至不起作用,而不是在“产品”设置器中设置它。
我认为让我重回正轨的另一件事是,当我提供一个以主窗体创建的模拟数据访问层时,一切正常。
此外,当我将 nHibernate 制作的 IList 复制到 IBindingList 时,一切都再次正常。
所以问题是我认为线程和 NotifyPropertyChanged 事件在使用某些数据源时会以某些方式丢失(希望我能比这更明确!)
我将继续研究解决此问题的更好方法,而不是将 IList 复制到 IBindingList - 也许我需要了解线程编组。
编辑
我现在已经开发了一个解决方案来解决这个问题,并且我认为我理解让我感到困惑的地方 - 似乎除了基本属性数据绑定之外的任何东西都不能很好地用于不是从 BindingList 派生的列表 - 只要我试图将数据绑定到触发链式 NotifyPropertyChanged 事件的属性,事情变得混乱,我的事件丢失了。
我现在拥有的数据访问解决方案是使用 Rob Conery IRepository 模式的变体,将我的集合返回为我创建的自定义类,一个从 BindingList 派生的 SortableBindingLazyList,实现 Sort Core 方法以及将其内部列表存储为查询,从而延迟列表实现。
【讨论】:
以上是关于WinForms 数据绑定和外键关系的主要内容,如果未能解决你的问题,请参考以下文章