WinForms数据绑定和外键关系
我正在开发一个WinForms应用程序(.Net 3.5,没有WPF),我希望在该应用程序中能够在数据绑定的DataGridView中显示外键查找。
这种关系的一个例子是我有一张OrderLines表。订单行与产品具有外键关系,而产品与产品类型又具有外键关系。
我想要一个数据绑定的DataGridView,其中每一行代表一个订单行,以显示该行的产品和产品类型。
用户可以直接向网格添加或者编辑订单行,并从comboBoxColumn中选择订单行的产品,然后应在同一行中更新producttype列,显示所选产品的产品类型。
到目前为止,最合适的方法是引入一个表示订单行的域对象,然后将DataGridView绑定到这些订单行的集合。然后,我向订单项对象添加属性以公开产品和产品类型,并引发相关的notifypropertychanged事件以使所有内容保持最新。然后,在我的订单行存储库中,可以连接此订单行对象与数据库中三个表之间的映射。
这适用于数据绑定方面,但是必须手动对存储库中的所有OR映射进行编码似乎很糟糕。我以为nHibernate可以帮助完成此连接,但是正在努力通过似乎可以正常工作的所有外键来进行映射(对订单行产品的外键查询会根据外键创建正确的产品对象),直到我尝试为止要进行数据绑定,我无法获取数据绑定的ID列来更新我的产品或者产品类型对象。
即使在正确的球场上,我的一般方法也可以吗?如果是,那么什么是映射问题的好解决方案?
或者,是否存在更好的数据绑定行解决方案,包括我什至没有考虑的外键查找?
解决方案
回答
欢迎来到StackOverflow :)
通常,我们要做的是基于两个值ValueMember和DisplayMember下拉列表中的信息。
ValueMember是实际控件值的来源(这将是订单行中的键值),显示成员是显示给用户的值而不是该值(这是FK值)。
没有特定的原因不能只返回所需的所有数据并设置这些属性吗?
回答
这是一个很好的"如何做"视频,演示了数据绑定:
http://windowsclient.net/learn/video.aspx?v=52579
回答
我最初的问题显然不清楚,对此感到抱歉。
问题不在于一般情况下与DataGridView的数据绑定,也不在于DataGridViewComboBoxColumn的实现,正如已经正确回答的人们所说的那样,这在Web上已得到很好的记录。
我一直试图解决的问题是通过关系向下钻取的属性的刷新。
在我的订单示例中,当我更改"产品"列的值时,即使在代码中设置属性并触发NotifyPropertyChanged事件,"产品类型"列也不会被更新。 (在调试中,我转到所有正确的位置)
反复研究之后,我意识到当我直接设置数据源的" Product Type"属性,而不是在" Product" setter中进行设置时,这甚至都行不通。
我相信让我回到正确轨道上的另一件事是,当我提供以主窗体创建的模拟数据处理层时,一切正常。
另外,当我将nHibernate制作的IList复制到IBindingList时,一切都很好。
因此,问题在于我认为在使用某些数据源时,以某些方式会丢失线程并丢失NotifyPropertyChanged事件(希望我能做得更好!)
与将IList复制到IBindingList相比,我将继续研究解决此问题的更好方法,也许我需要了解线程编组。
编辑
我现在已经开发出一种解决方案,可以解决该问题,并认为我基本上理解了令我感到困惑的地方,似乎除了基本属性数据绑定之外,对于试图从数据绑定中获取的不是从BindingList派生出来的列表,它都不能很好地发挥作用对于触发了链式NotifyPropertyChanged事件的属性,事情变得一团糟,我的事件迷失了。
我现在使用的数据访问解决方案使用的是Rob Conery IRepository模式的一种变体,将我的集合绑定为我创建的自定义类,该类是从BindingList派生的SortableBindingLazyList,实现了Sort Core方法并将其内部列表存储为查询,延迟列表实现。
回答
好吧,我不知道DataGridView是否支持它,但是当我们执行常规WinForms数据绑定(例如,绑定到常规TextBox)时,可以使用属性路径浏览对象关系。
像这样的东西:
myTextBox.DataBindings.Add("Text", anOrderLine, "OrderedPart.PartNumber");
值得一看,这是否也适用于情况。
回答
我认为我们遇到的问题是,当我们绑定到网格时,仅支持INotifyPropertyChanged是不够的,但是我们必须在IBindingList实现中触发ListChanged事件,并确保覆盖并为SupportsChangeNotification返回true财产。如果我们没有为此返回true,则网格将不会寻找它来知道数据是否已更改。
在.NET 2.0+中,我们可以使用BindingList类创建一个通用集合,这将处理大多数麻烦事(只是不要忘记重写并为SupportsChangeNotification属性返回true)。
如果用于数据绑定的类具有作为集合的属性(例如IBindingList或者BindingList),则可以将外键网格直接绑定到该属性。在窗体设计器中配置绑定时,只需选择collection属性作为网格的数据源。它应该"正常工作"。唯一的偷偷摸摸的部分是确保我们以正确的方式处理空或者空集合。