使用EF POCO对象获取Readonly Databind

时间:2011-03-22 16:49:50

标签: entity-framework data-binding entity-framework-4 binding

我在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派生对象? (使单元测试变得困难。)

感谢。

1 个答案:

答案 0 :(得分:4)

问题可能是您的POCO示例中OrdersOrderDetails个集合的类型为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可编辑。