我在WPF中使用EF4。我以Master-Detail样式数据绑定到DataGrid。想想Northwind客户 - >订单 - >订单明细。
我发现当我使用POCO对象时,Orders和OrderDetails网格是只读的。如果我恢复使用设计器生成的实体,它们就会变得可编辑。
绑定XAML如下所示:
<Window.Resources>
<CollectionViewSource x:Key="CustomersViewSource" d:DesignSource="{d:DesignInstance my:Customer, CreateList=True}" />
<CollectionViewSource x:Key="CustomersOrdersViewSource" Source="{Binding Path=Orders, Source={StaticResource CustomersViewSource}}" />
</Window.Resources>
<Grid DataContext="{StaticResource CustomersViewSource}">
<DataGrid ItemsSource="{Binding}" >
<DataGrid ItemsSource="{Binding Source={StaticResource CustomersOrdersViewSource}}" >
(当然,我删除了与数据绑定无关的属性。)
然后是绑定上下文实例的标准表单加载事件:
Dim NorthwindEntities As BindTest.NorthwindEntities = New BindTest.NorthwindEntities()
Dim CustomersViewSource As System.Windows.Data.CollectionViewSource = CType(Me.FindResource("CustomersViewSource"), System.Windows.Data.CollectionViewSource)
CustomersViewSource.Source = NorthwindEntities.Customers
网格填充,但第二个是只读,如果我正在使用我的POCO对象,如果它们是标准的EF生成对象,则可编辑。
密钥似乎在实体的导航属性中。我的POCO对象使用:
Public Overridable Property Orders() As ICollection(Of Order)
Get
If _Orders Is Nothing Then _Orders = New HashSet(Of Order)
Return _Orders
End Get
Set(ByVal value As ICollection(Of Order))
_Orders = value
End Set
End Property
而EF对象要复杂得多:
<XmlIgnoreAttribute()>
<SoapIgnoreAttribute()>
<DataMemberAttribute()>
<EdmRelationshipNavigationPropertyAttribute("NorthwindModel", "FK_Order_Details_Orders", "Orders")>
Public Property Order() As Order
Get
Return CType(Me, IEntityWithRelationships).RelationshipManager.GetRelatedReference(Of Order)("NorthwindModel.FK_Order_Details_Orders", "Orders").Value
End Get
Set
CType(Me, IEntityWithRelationships).RelationshipManager.GetRelatedReference(Of Order)("NorthwindModel.FK_Order_Details_Orders", "Orders").Value = value
End Set
End Property
由于缺少一些更好的措辞,EntityCollection类型的属性似乎有些神奇。 ICollection不是只读接口,HashSet也不是只读。
有关如何让POCO在这里工作的任何想法,还是我坚持使用EF派生对象? (使单元测试变得困难。)
感谢。
答案 0 :(得分:4)
问题可能是您的POCO示例中Orders
和OrderDetails
个集合的类型为ICollection<T>
/ HashSet<T>
。 WPF数据网格内部不能直接使用集合,而是使用关联的“集合视图”。将集合绑定到DataGrid时,WPF绑定引擎会根据集合的类型创建此内部集合视图。
如果您的集合仅实现IEnumerable
或仅ICollection
,则创建的集合视图的类型为CollectionView
,不的类实现{{1} }}。这就是为什么在将HashSet绑定到DataGrid时无法编辑DataGrid的原因。
DataGrid需要一个集合视图,它实现IEditableCollectionView
以允许编辑。这是例如IEditableCollectionView
(也来自ListCollectionView
)。如果源集合实现CollectionView
接口,WPF将创建此类集合视图。
因此,要解决此问题,您应该将POCO的IList
属性类型更改为Orders
:
IList
修改强>
根据@Allon Guralnek的评论,有必要实施非通用 Public Overridable Property Orders() As IList(Of Order)
Get
If _Orders Is Nothing Then _Orders = New List(Of Order)
Return _Orders
End Get
Set(ByVal value As IList(Of Order))
_Orders = value
End Set
End Property
界面来获取可编辑的DataGrid。这是IList
的情况,因此上面的代码仍然有效。其他仅实现泛型 List(Of T)
但不实现非泛型IList(Of T)
的实现不会使DataGrid可编辑。