あなたの主な問題は、懸念の正しい分離であるようです。WPF と MVVM は、Windows 開発の従来の方法とはかなり異なります。
最初に、ここで何かを整理しましょう。用語との混乱かもしれませんが、言及します。
MVVM では、モデルはデータの保存に使用されません。
データの保持に使用できますか? はい。
データを保持するために使用する必要がありますか? いいえ。
データの保持と変換はビューモデルの仕事です。モデルの仕事はコンジットとして機能することであり、データを取得します (つまり、リポジトリから取得したり、WCF サービスとの通信を制御したりします)。モデルがデータを保持している場合、ビューがモデルにバインドされることを意味しますが、これは間違っています。
あなたが話しているデータの一部は、ビューにも保持する必要があります。何かが重複しているかどうかの判断は、ビューモデルで、場合によってはモデルでも判断できます (モデルはビジネス ルールを適用し、通過するデータにフラグを付けることができます)。複製に表示する色はビューの責任です。その色がビジネス ルールによって決定されない限り、ビューモデルに移動できます。
ObservableCollection にバインドしています。これは、DataGrid のようなリピーター タイプのコントロールを使用していることを示しています。この場合、各行は他の行を認識しません。ある行のデータ オブジェクトからプロパティ変更イベントを発生させた場合、別の行はそれをまったく認識しないため、それらの変更に基づいてレンダリング方法を変更することはできません。このような場合、関連する行のデータをオブザーバー パターンの方法で調整する必要があります。
このような相互依存関係がある場合、実際の各データ オブジェクトを、ファサードとして機能する別の軽量オブジェクトにラップするのが普通です。これを、各行のデータ オブジェクトにビューモデルがあると呼ぶ人もいます。たとえば、単純な Customer オブジェクトは次のとおりです。
public class Customer
{
public string FirstName {get; set;}
public string Surname {get; set;}
}
これをビューモデルの ObservableCollection に保存すると、ラップできます。
public class CustomerWrapper
{
private Customer _customer;
public CustomerWrapper (Customer customer)
{
_customer = customer;
}
public bool HasRelation{get;set;}
public Customer Customer { get {return _customer;}}
}
Customer オブジェクト間の相互依存性を示したい場合 (たとえば、それらがファミリの一部である場合) HasRelation
、CustomerWrapper オブジェクトが作成されたら、プロパティを設定するだけです。
var myCustomerList = GetMyCustomers();
foreach (var customer in myCustomerList)
{
myObservableCollection.Add(new CustomerWrapper(customer)
{
HasRelation = myCustomerList.Where(p => string.Equals(p.Surname, customer.Surname).Count() > 1)
});
}
リピーター コントロールを ObservableCollection にバインドすると、HasRelation プロパティを使用して UI の色などを制御できます。
これは不自然な例であり、簡潔にするために意図的に省略していることに注意してください。ビューモデルが各 Customer オブジェクトのプロパティ変更イベントをサブスクライブしている場合、必要に応じて CustomerWrapper オブジェクトを更新できます。相互依存関係の状態は、データを表示するたびに判断できるため、データと共にリポジトリに保存する必要はありません。私が省略したことの 1 つは、FirstName および Surname プロパティをラップすることでした。それらのラッパー プロパティを配置することも、XAML のバインディングでパスを使用して、ネストされたオブジェクトにドリルダウンすることもできます。