似乎您的主要问题是正确分离关注点。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;}}
}
现在,如果您想指示您的客户对象之间的相互依赖关系,例如,如果它们是一个家庭的一部分,您可以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 对象。相互依赖状态不需要与存储库中的数据一起存储,因为您可以在每次显示数据时确定它。我省略的一件事是包装 FirstName 和 Surname 属性 - 您可以为它们放入一个包装器属性,或者您可以简单地使用 XAML 绑定中的路径来向下钻取到嵌套对象。