0

データグリッドを ViewModel 要素の監視可能なコレクションにバインドし、それを NotifyCollectionChangedEventHandler イベントにリンクしました。

obsListOfClients = new ObservableCollection<ClientVM>();
foreach (var c in contexte.listOfClients)
{
    ClientVM cvm = new ClientVM(c);
    obsListOfClients.Add(cvm);
}
obsListOfClients.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(collectionOfClientssChanged);

vue でデータグリッドを編集しています。コンテンツを追加/削除、更新し、これらの操作のそれぞれが完了したときに通知を受け取ることができるようにしたい: 私はこの関数を作成しました:

 void collectionOfClientssChanged(object sender, NotifyCollectionChangedEventArgs e)
 {
     switch (e.Action)
     {
         case NotifyCollectionChangedAction.Add:
         //Ajouter dans la base de données :
             for(int i = 0; i<e.NewItems.Count;i++)
             {
                 ClientVM item = e.NewItems[i] as ClientVM;
                 contexte.ListOfClientsToAdd.Add(item.Client);
             }
             break;

         case NotifyCollectionChangedAction.Remove:
             for(int i = 0; i < e.OldItems.Count; i++)
             {
                 ClientVM item = e.OldItems[i] as ClientVM;
                 contexte.ListOfClientsToRemove.Add(item.Client);
             }
             break;

         case NotifyCollectionChangedAction.Replace:
             for(int i = 0; i < e.OldItems.Count; i++)
             {
                 ClientVM item = e.OldItems[i] as ClientVM;
                 contexte.ListOfClientsToUpdate.Add(item.Client);
             }
             break;
     }
}

次に、3 つのリスト (ListOfClientsToUpdate、ListOfClientsToRemove、ListOfClientsToAdd) を使用して変更のトレースを保持し、すべての変更を一度データベースにプッシュできるようにします。

問題は、 datagrid で行を追加または削除すると、通知が表示され、リストが要素で満たされるのに、既存の行の内容を更新すると、コレクションの変更に関する通知さえ表示されないことです! !! そのため、既存の要素に対する変更の痕跡を残すことができません!

何か案が ?どうもありがとう :) :)

4

3 に答える 3

1

これは、コレクションが実際には変更されないためです。コレクション内の各要素は、オブジェクトへの参照です。オブジェクトは変更されますが、参照は同じままです。したがって、コレクションは変更されません。

監視可能なコレクションに対する更新操作は、要素を別の要素に置き換えることを意味しますそれはあなたの場合に起こることではありません。

コレクション内のオブジェクトのプロパティ変更通知にも登録する、問題のより複雑なソリューションが必要になります。

于 2013-02-27T16:14:54.740 に答える
1

リスト内の要素への変更を検出するには、ClientVM のプロパティの変更をリッスンする必要があります。これは、クライアントのリストへの変更としてカウントされないためです。

非常に大まかに言うと、次のようなことができます。

obsListOfClients = new ObservableCollection<ClientVM>();
foreach (var c in contexte.listOfClients)
{
    ClientVM cvm = new ClientVM(c);
    // NEW BIT HERE
    cvm.PropertyChanged += ClientVMChangedEventHandler;
    obsListOfClients.Add(cvm);
}
obsListOfClients.CollectionChanged += ...;

private void ClientVMChangedEventHandler(object sender,
                                         PropertyChangedEventArgs e)
{
    contexte.ListOfClientsToUpdate.Add(((ClientVM)sender).Client);
}

新しいアイテムを追加するときも同じようにします。アイテムを削除するときは、イベント ハンドラーを削除することを忘れないでください。

于 2013-02-27T16:13:51.360 に答える
1

インターフェイスをClientVM実装していますか? INotifyPropertyChangedまた、アイテムではなく、コレクション自体の変更を監視しています。

コレクション アイテムのCollectionChangedプロパティが変更されたときにイベントが呼び出されることは想定されていませんが、コレクション自体が変更された場合にのみ呼び出されます。

個々のアイテムの変更に関する通知を受け取るには、上記のコードで追加/置換/削除されたPropertyChanged各インスタンスのイベントを購読/購読解除することをお勧めします。追加および削除の例は次のようになります。ClientVMObservableCollection

switch (e.Action)
{
    case NotifyCollectionChangedAction.Add:
        for(int i = 0; i<e.NewItems.Count;i++)
        {
            ClientVM item = e.NewItems[i] as ClientVM;
            item.PropertyChanged += ItemPropertyChanged;
            contexte.ListOfClientsToAdd.Add(item.Client);
        }
        break;

    case NotifyCollectionChangedAction.Remove:
        for(int i = 0; i < e.OldItems.Count; i++)
        {
            ClientVM item = e.OldItems[i] as ClientVM;
            item.PropertyChanged -= ItemPropertyChanged;
            contexte.ListOfClientsToRemove.Add(item.Client);
        }
        break;
}

ItemPropertyChangedイベント ハンドラーである場合:

private void ItemPropertyChanged(object sender, PropertyChangedEventArgs e)
{
    // Handle property change here
}
于 2013-02-27T16:14:01.797 に答える