我在wpf + mvvm中有一个场景,即如果我的特定属性在viewmodel1中更改,那么我想通知viewmodel2具有可观察的集合属性" A"已经改变了 1)我想为所有特殊财产解雇它。
我试过下面的代码,但没有工作。请告诉我如何做到这一点。
public class Model1 : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
// Create custom event
public event EventHandler NotifyChange;
private string testProperty;
public string TestProperty
{
get
{
return testProperty;
}
set
{
testProperty = value;
// If changing properties, fire your OnPropertyChanged to update UI
OnPropertyChanged("TestProperty");
}
}
private void OnPropertyChanged(string propName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propName));
// Fire your custom event if a property changed
NotifyChange(this, null);
}
}
}
public class Model2 : INotifyCollectionChanged
{
public event NotifyCollectionChangedEventHandler CollectionChanged;
public Model2()
{
// Assuming there is an accessible instance of model1
Model1 m1Instance = new Model1();
// Hook up your NotifyChange event from model1
m1Instance.NotifyChange += Model1Changed;
}
private void Model1Changed(object sender, EventArgs e)
{
// this will be triggered on change in model1
}
private void OnCollectionChanged(object singleObject)
{
if (CollectionChanged != null)
CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset, singleObject));
}
}
答案 0 :(得分:1)
我的建议是调查PubSub
事件。
我这样做的建议是使用棱镜。以下是一些更多信息:http://www.c-sharpcorner.com/UploadFile/5ffb84/prism-event-aggregator-in-wpf-with-mvvm/
在这种情况下,您将坚持正确的MVVM做法。
以下是MSDN的有用指南:https://msdn.microsoft.com/en-us/library/ff649664.aspx
对如何工作以及如何使用/实现它进行非常好的阅读。
这会有效,但如果可能的话,我仍然会推迟使用PubSub事件。
你可以试试这个:
public class Model1 : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private string _property;
public string Property
{
get { return _property; }
set
{
_property = value;
OnPropertyChanged("Property");
}
}
private void OnPropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
public class Model2
{
public Model2()
{
// You might be storing your Model1 as a property in the Model2?
// I don't know, but I've put it in the constructor just for example.
var model1 = new Model1();
model1.PropertyChanged += OnModel1PropertyChanged;
}
private void OnModel1PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "Property")
{
// Do stuff here when the right property has changed in model 1
}
}
}
我在new
的构造函数中只有Model1
代表Model2
作为示例 - 您可能正在分配它并将其作为字段或属性存储在{{1}的其他位置1}} ViewModel。
如果在ViewModels(父虚拟机>子虚拟机)中有ViewModel,这可能特别有用。
我使用父>子VM很常见,我认为它不符合MVVM最佳实践,但我仍然使用Model2
,而不是{{1 }}Š
作为旁注,如果您使用的是C#6:
EventAggregator
代替“魔术字符串”(例如event
)。这使得重构变得更容易,编译器可以告诉您错误 - 但基本上可以完成同样的工作。在nameof(Property)
ter "Property"
来电中使用此功能
OnPropertyChanged()
关键字,其原理与上述相同。像这样:set
nameof
。将if (e.PropertyName == nameof(Model1.Property)) ...
的方法体更改为漂亮的单行,同时仍然执行相同的工作我会始终看看在可能的情况下坚持适当的MVVM做法。
我每天都使用Prism的PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
,并会发誓。
阅读 PubSub事件(您可以使用任何类型的事件聚合器,但我会说使用Prism's,最好)
希望这有帮助! :)
答案 1 :(得分:0)
那是因为您没有注册PropertyChanged
。您正在NotifyChange
注册您的事件处理程序,以便PropertyChanged
中的Model1
为NULL
,因此NotifyChange
不会被触发。
因此,您需要按照以下方式实施OnPropertyChanged
:
private void OnPropertyChanged(string propName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propName));
if (NotifyChange != null)
NotifyChange(this, null);
}
最后,如果您希望针对特定媒体资源触发NotifyChange
,请在触发事件之前调整上面的代码以检查propName
。
答案 2 :(得分:0)
如果这只是为了通知Model2,我认为你不需要所有这些实现。你可以做点什么
public string TestProperty
{
get
{
return testProperty;
}
set
{
testProperty = value;
// If changing properties, fire your OnPropertyChanged to update UI
OnPropertyChanged("TestProperty");
//Here you can call a method of Model2 sating that its changed
Model2 m2Instance = new Model2();
m2Instance.ValueChanged();
}
}
在模型2中添加方法ValueChanged。