处理C#中的属性更改的更好方法

时间:2016-08-24 12:51:48

标签: c# wpf mvvm

我正在构建一个MVVM应用程序,其中ToBeListened类有几个属性PropertyAPropertyB,我想听听它们。

public class ToBeListened : INotifyPropertyChanged
{

    private double _propertyA;
    private string _propertyB;
    /*Here I'm omitting the update part where NotifyPropertyChanged gets called*/
    public double PropertyA{get; set; }
    public double PropertyB{get; set; }

    public event PropertyChangedEventHandler PropertyChanged;

    protected void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

这两个属性由Listener类监听,因此我在其中实现了一个EventHandler,用于侦听ToBeListened对象。

public class Listener
{

     private ToBeListened toBeListenedObject; 

     public Listener()
     {  
        toBeListenedObject = new ToBeListened();
        toBeListenedObject.PropertyChanged += newPropertyChangedEventHandler(PropertyListener_PropertyChanged);
     }

     private void PropertyListener_PropertyChanged(object sender, PropertyChangedEventArgs e)
     {
        switch(e.PropertyName)
        {
          case "PropertyA":
          {
            /*...DO SOMETHING...*/
          }
          case "PropertyB":
          {
            /*...Do something else...*/
          }
    }

问题是,我真的不喜欢我找到的这个解决方案。 switch-case不是多态友好的,所以

  1. 有更好的方法吗?也许使用重载的东西? (如private void PropertyListener_PropertyChanged(double sender, PropertyChangedEventArgs e)
  2. 最重要的是,编写像这样的ViewModel是对的吗?

3 个答案:

答案 0 :(得分:4)

我喜欢Josh Smith的PropertyObserver,你可以在http://mvvmfoundation.codeplex.com/获得(Josh在https://joshsmithonwpf.wordpress.com/2009/07/11/one-way-to-avoid-messy-propertychanged-event-handling/的一些文档)。这是一个很好的类,它封装了您正在讨论的管道逻辑,因此您可以专注于处理对某些属性的更改。因此,在您的情况下,您可以编写如下代码:

var observer = new PropertyObserver<ToBeListened>(toBeListenedObject)
                  .RegisterHandler(tbl => tbl.PropertyA, tbl => HandlePropertyA(tbl))
                  .RegisterHandler(tbl => tbl.PropertyB, tbl => HandlePropertyB(tbl));

您可以通过在您的解决方案中安装MVVM Foundation nuget包来开始使用它。 ID是MvvmFoundation.Wpf。

答案 1 :(得分:1)

在过去,为了这个目的,我使用了从Dictionary<string, Action>派生的小班。它是这样的:

public class PropertyChangedHandler : Dictionary<string, Action>
{
    public PropertyChangedHandler(INotifyPropertyChanged source)
    {
        source.PropertyChanged += Source_PropertyChanged;
    }

    private void Source_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        Action toDo;
        if (TryGetValue(e.PropertyName, out toDo))
        {
            toDo();
        }
    }
}

然后你的听众看起来像这样:

public class Listener
{
    private ToBeListened toBeListenedObject = new ToBeListened();

    PropertyChangedHandler handler;

    public Listener()
    {
        handler = new PropertyChangedHandler(toBeListenedObject)
                    {
                        { "PropertyA", DoA },
                        { "PropertyB", DoB }
                    };
    }

    private void DoB()
    {            
    }

    private void DoA()
    {            
    }
}

这只是一个给你一个想法的例子 - 当然,它可以扩展到更复杂的目的。

答案 2 :(得分:0)

我认为MVVM Light框架(或库?)有你需要的东西。看看他们的ObservableObject课程http://www.mvvmlight.net/help/SL5/html/d457231f-6af7-601d-fa1f-1fe7c9f60c57.htm

基本上它的作用是使你的物体可以观察到。