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