1

我有一个使用 MVVM 模型和实体框架 5 进行数据访问的 WPF 应用程序。我有一个用户控件,其中包含员工的主/详细视图。员工列表的列表视图和“详细信息”网格,其数据上下文设置为列表视图的选定员工。在该网格中,我有一个数据网格,它绑定到所选员工的导航属性(名为employee_certification 的属性)。所有绑定都正常工作并且没有错误,即使在输出窗口中也是如此。

问题:我的问题是我无法检测到用户是否对导航属性的记录进行了任何更改。我目前使用更改跟踪器来测试实体中的更改以启用某些命令按钮,例如保存、撤消等。但是更改跟踪器从未检测到导航属性(称为雇员认证)中的更改。

以下是我从模型中获取员工实体的方法:

    Public Function GetEmployee_All(Context As FTC_Context) As ObservableCollection(Of employee) Implements IEmployeeDataService.GetEmployee_All
        Dim employees = Context.employees.Include("employee_certification").ToList            
        Return New ObservableCollection(Of employee)(employees)
    End Function

这是导航属性到数据网格的绑定。(有效,这意味着它确实显示了正确的记录)

<DataGrid  Grid.Column="1" Grid.Row="2" MinWidth="350"        
            ItemsSource="{Binding ElementName=DetailControl, Mode=TwoWay, Path=DataContext.employee_certification}" 
            CanUserAddRows="False" CanUserDeleteRows="False" >
    <DataGrid.Columns>
    </DataGrid.Columns>
</DataGrid>

即使绑定有效并且显示了正确的记录,我也无法确定用户是否对导航属性的记录进行了更改。

目标:如果可能的话,我希望能够通过上下文本身检测变化。我不想编写一个帮助类来将当前记录与数据库原件进行比较。有人可以帮我这样做吗?

编辑#1: 我认为这可能与数据网格有关。我在我的应用程序的另一个用户控件中有以下列表视图,并且可以通过 EF 上下文跟踪对列表视图记录中的记录字段所做的任何更改。

绑定 vendor_account 是实体 vandor 的导航属性的列表视图:

 <ListView Grid.Column="1" Grid.Row="2"
           Style="{DynamicResource FTC_SubListView}"
           ItemContainerStyle="{DynamicResource FTC_SubListViewItem}"
           ItemsSource="{Binding vendor_account, Mode=TwoWay}"
           ItemTemplate="{DynamicResource FTC_VendorAccountsTemplate}"  />

以下是我如何确定是否有更改以在我的视图中启用保存按钮:

    Private Function CanSaveExecute() As Boolean
        If _Selection.HasErrors = False Then
            If (From entry In Context.ChangeTracker.Entries(Of vendor)() Where entry.Entity.idVendor = _Selection.idVendor And entry.State = EntityState.Modified Select entry).Count > 0 Then
                Return True
            ElseIf (From entry In Context.ChangeTracker.Entries(Of vendor_account)() Where entry.Entity.idVendor = _Selection.idVendor And (entry.State = EntityState.Modified Or entry.State = EntityState.Added) Select entry).Count > 0 Then
                Return True
            Else
                Return False
            End If
        Else
            Return False
        End If
    End Function

但如果我对数据网格使用以下内容,它永远不会对emplopyee_certification 导航属性进行更改计数:

    Private Function CanSaveExecute() As Boolean
        If _Selection.HasErrors = False Then
            If (From entry In Context.ChangeTracker.Entries(Of employee)() Where entry.Entity.idEmployee = _Selection.idEmployee And entry.State = EntityState.Modified Select entry).Count > 0 Then
                Return True
            ElseIf (From entry In Context.ChangeTracker.Entries(Of employee_certification)() Where entry.Entity.idEmployee = _Selection.idEmployee And entry.State = EntityState.Modified Select entry).Count > 0 Then
                Return True
            Else
                Return False
            End If
        Else
            Return False
        End If
    End Function

有谁知道为什么我的列表视图允许更改跟踪器从更改跟踪器中查看 x 个已更改的实体,但不能使用数据网格?

编辑#2

好的,所以我缩小范围,我将列表视图和数据网格放在同一个用户控件上,并以相同的方式将它们绑定到对象的数据上下文的导航属性,如上所述。员工具有作为链接记录的认证,这是员工对象的导航属性 (employee_certification)。

如果我对employee_certification 记录使用列表视图,那么当我对这些记录进行更改时,我可以查询更改跟踪器以计算更改并在计数大于零时启用保存和撤消按钮。

 From entry In Context.ChangeTracker.Entries(Of employee_certification)() Where entry.Entity.idEmployee = _Selection.idEmployee And entry.State = EntityState.Modified Select entry).Count

当我使用数据网格并更改employee_certification 记录中的任何字段时,更改跟踪器不会将其中任何一个标记为已修改。

这是数据网格/列表视图的定义方式

 <DataGrid  Grid.Column="1" Grid.Row="2" MinWidth="350"        
            ItemsSource="{Binding employee_certification, Mode=TwoWay}" 
            CanUserAddRows="False" CanUserDeleteRows="False" >
    <DataGrid.Columns>
        <!--  Custom Defined Columns Go Here  -->
    </DataGrid.Columns>
</DataGrid>
<ListView Grid.Column="1" Grid.Row="3"
            Style="{DynamicResource FTC_SubListView}"
            ItemContainerStyle="{DynamicResource FTC_SubListViewItem}"
            ItemsSource="{Binding employee_certification, Mode=TwoWay}"
            ItemTemplate="{DynamicResource MyTemplate}">
</ListView>

由于内置排序等,我想使用数据网格。

编辑问题#2:为什么更改跟踪器跟踪列表视图编辑中的更改而不是数据网格编辑?

4

1 回答 1

0

这很令人沮丧。正如标题所暗示的,我认为问题出在实体框架、可观察集合和数据网格的一些交互上。事实证明,这只是 DataGridTemplateColumn 的绑定声明的问题。

根据此SO ANSWER,当使用您自己的 DataGridTemplateColumn 时,DataGrid 将所有绑定上的 UpdateSourceTrigger 更改为 Explicit。这必须由事件处理。但是,我正在使用 MVVM 模式并且不希望事件来处理单元格更改。我希望更改自动反映回我的视图模型中的集合,所以我必须像这样显式声明列绑定:(即对于组合框)

 SelectedValue="{Binding idCertification, Mode=TwoWay, ValidatesOnDataErrors=True, UpdateSourceTrigger=LostFocus}"

我必须添加 UpdateSourceTrigger=LostFocus 才能将更改反映回可观察的集合。现在我可以直接绑定到导航属性,并使用实体框架中的Context.changeTracker来计算更改(employee_certification,如上面的问题所示),以启用保存和撤消命令。

两天的搜索发现它只是对绑定的简单添加,arrrgh。

于 2013-03-27T20:27:50.433 回答