如果viewmodel1属性更改,则通知viewmodel2

时间:2016-07-15 07:15:00

标签: c# wpf silverlight mvvm

我在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));
    }
}

3 个答案:

答案 0 :(得分:1)

使用PubSub事件

我的建议是调查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中的Model1NULL,因此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。