1

データアクセスにMVVMモデルとEntityFramework5を使用するWPFアプリケーションがあります。従業員のマスター/詳細ビューを含むユーザーコントロールがあります。従業員のリストのリストビューと、データコンテキストがリストビューの選択された従業員に設定された「詳細」グリッド。そのグリッド内に、選択した従業員のナビゲーションプロパティ(employee_certificationという名前のプロパティ)にバインドされたデータグリッドがあります。すべてのバインディングは正しく機能し、出力ウィンドウでもエラーは発生しません。

問題:私の問題は、ユーザーがナビゲーションプロパティのレコードに変更を加えたかどうかを検出できないことです。現在、変更トラッカーを使用してエンティティの変更をテストし、保存、元に戻すなどの特定のコマンドボタンを有効にしています。ただし、変更トラッカーはナビゲーションプロパティ(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:

 <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/listviewの定義方法は次のとおりです

 <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のバインディング宣言の問題にすぎませんでした。

このSOANSWERに従って、独自のDataGridTemplateColumnを使用すると、DataGridはすべてのバインディングのUpdateSourceTriggerをExplicitに変更します。これはイベントによって処理される必要があります。ただし、MVVMパターンを使用しているため、セルの変更を処理するイベントは必要ありません。ビューモデルのコレクションに変更を自動的に反映させたいので、次のように列バインディングを明示的に宣言する必要があります:(つまりコンボボックスの場合)

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

変更を監視可能なコレクションに反映させるには、UpdateSourceTrigger=LostFocusを追加する必要がありました。これで、ナビゲーションプロパティに直接バインドし、エンティティフレームワークのContext.changeTrackerを使用して、保存および元に戻すコマンドを有効にするために(上記の質問に示されているように、employee_certificationの)変更をカウントできます。

それを見つけるための2日間の検索は、バインディングへの単純な追加でした。

于 2013-03-27T20:27:50.433 に答える