我使用WPF MVVM,Caliburn Micro和WCF服务来构建我的第一个生产应用程序。
我已经到了需要我的ViewModel来跟踪模型中各个属性的变化的地步。我举个例子。我的VM具有以下属性:
public OrdenesTransporteWCFModel OrdenTransporte { get; set; }
public List<EnumeradorWCFModel> TiposCarga { get; set; }
public List<EnumeradorWCFModel> TiposCamion { get; set; }
public List<EnumeradorWCFModel> MediosContacto { get; set; }
OrdenesTransporteWCFModel是一个来自WCF服务的模型,我的视图可能如下所示:
<ComboBox ItemsSource="{Binding Path=TiposCarga}" SelectedValuePath="ID" DisplayMemberPath="Descripcion" SelectedValue="{Binding Path=OrdenTransporte.ID_TipoCarga}"></ComboBox>
<ComboBox ItemsSource="{Binding Path=TiposCamion}" SelectedValuePath="ID" DisplayMemberPath="Descripcion" SelectedValue="{Binding Path=OrdenTransporte.ID_TipoMovil}"></ComboBox>
<ComboBox ItemsSource="{Binding Path=MediosContacto}" SelectedValuePath="ID" DisplayMemberPath="Descripcion" SelectedValue="{Binding Path=OrdenTransporte.ID_MedioContacto,ValidatesOnDataErrors=True}"></ComboBox>
<TextBox IsEnabled="False" Text="{Binding Path=OrdenTransporte.Numero}"></TextBox>
<DatePicker SelectedDate="{Binding Path=OrdenTransporte.FechaConfeccion}"></DatePicker>
正如您所看到的,我将控件绑定到模型中的各个属性(OrdenTransporte)。
现在我需要的是我的VM来跟踪这些属性的变化:例如,我的VM属性 HasChange 中有一个bool,如果任何字段发生变化,我需要激活它。我还有一个方法 TipoCamionChange ,如果ID_TipoCamion属性发生变化我需要触发。
有什么方法可以实现吗? 谢谢!
修改
正如Martin建议的那样,我在我的模型上实现了INotifyPropertyChange,并尝试将我的模型订阅到我的模型上的propertychange事件,如下所示:
OrdenTransporte = _svc.OrdenesTransporte_GetById(IDOrden);
OrdenTransporte.PropertyChanged += Model_PropertyChanged;
private void Model_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "ID_Cliente")
{
CargarDirecciones();
}
}
问题在于,当我订阅我的vm模型PropertyChange时,模型中的数据已经发生了变化,因此从不调用PropertyChanged。如果我这样做:
OrdenTransporte.PropertyChanged += Model_PropertyChanged;
OrdenTransporte = _svc.OrdenesTransporte_GetById(IDOrden);
无论如何都不会触发事件,因为整个对象被WCF服务返回的对象替换,包括INotifyPropertyChange事件。任何想法?
答案 0 :(得分:1)
模型类是否实现***
?
然后,您可以在视图模型中将事件处理程序设置为模型类中的更改:
INotfiyPropertyChanged
您可以将多个模型对象的事件全部链接到同一个事件处理程序,然后设置 modelObject.PropertyChanged += ViewModelOnPropertyChanged;
private void ViewModelOnPropertyChanged(object sender, PropertyChangedEventArgs propertyChangedEventArgs)
{
// react to object change here
}
视图模型属性。
如果您的模型对象未实现HasChange
,我不知道解决方案。
答案 1 :(得分:1)
您可以使用Dynamic Castle(在代理中封装实例)或Fody(在编译时在后续步骤中修改IL)自动为模型属性添加IPNC支持。
更新:如果您的模型来自Web服务参考,那么他们已经拥有IPCN支持,您可以通过转到项目中自动生成的源代码来查看。您也可以在代码中确认:
using (var client = new ServiceReference1.Service1Client())
{
var data = client.GetData();
data.PropertyChanged += (s, e) =>
{
Debug.Assert(false, "PropertyChanged handler invoked.");
};
data.SomeMember = false; // <-- will cause the assert to trigger
}
答案 2 :(得分:0)
您应该使用ObservableCollection<T>
代替List<T>
和INotifyPropertyChanged。
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
private ObservableCollection<EnumeradorWCFModel> _tiposCarga;
public ObservableCollection<EnumeradorWCFModel> TiposCarga
{
get { return _tiposCarga; }
set
{
if (_tiposCarga != value)
{
_tiposCarga = value;
OnPropertyChanged(nameof(TiposCarga));
}
}
}