使用OnPropertyChanged创建具有公共属性的ViewModel?

时间:2012-07-01 07:26:44

标签: c# wpf design-patterns mvvm

我放心了我有很多具有这两个属性的模型视图模型

public Visibility OkButtonVisibility
{
get{  return _OkButtonVisibility;}
set{ 
_OkButtonVisibility = value;
RaisePropertyChanged("OkButtonVisibility");
}

}

public Visibility CancelButtonVisibility
{
get{  return _CancelButtonVisibility;}
set{ 
_CancelButtonVisibility = value;
RaisePropertyChanged("CancelButtonVisibility");
}

}

我想像这样为他们创建可附加的界面:

Interface IOKandCancelButtonsVM
{
 public Visibility OkButtonVisibility
{
get{  return _OkButtonVisibility;}
set{ 
_OkButtonVisibility = value;
RaisePropertyChanged("OkButtonVisibility");
}

}

public Visibility CancelButtonVisibility
{
get{  return _CancelButtonVisibility;}
set{ 
_CancelButtonVisibility = value;
RaisePropertyChanged("CancelButtonVisibility");
}

}

并让我的viewmodel使用它来继承它们,并让另一个接口使用像这样的代理属性

class VM1:BaseVM,IOKandCancelButtonsVM,IOtherCommonPropertyVM
{ 

} 

然后我重新启动了我的新界面并没有暗示INotifyChanged。 让IOKandCancelButtonsVM表达INotifyChanged是个不错的主意 并VM1明确表示BaseVM

我从未处理过两次继承相同接口的类,并且不知道该怎么做。

这只是一个例子,不到一半的虚拟机使用那些拥有几百个属性的虚拟机,许多属性共享数十个屏幕。我需要一个更优雅的解决方案,而不是将所有内容都粘贴到BaseViewModel

4 个答案:

答案 0 :(得分:2)

您的接口定义中不能有实现。这意味着您的IOKandCancelButtonsVM定义不正确。

  使用IOKandCancelButtonsVM实现BaseVM是不是一个坏主意

是的,这将是一个非常糟糕的主意 - 实际上是不可能的 - 接口无法实现或扩展类。

由于您询问了如何构建代码的意见,我也会将其抛弃:从viewmodel中删除对“visibility”的任何引用。 从您的viewmodel返回System.Visibility值。

viewmodel不应该对视图有任何了解。这样做的语义正确的方法是简单地从viewmodel返回一个标志,并使用转换器将其更改为绑定中的Visibility值 - 框架中甚至还有一个现成的转换器来执行此操作:{{3} }。尽量避免在VM中提及UI相关术语,即使它返回了一个bool - 这是一个很好的做法,可以导致更严格和更严格的代码,使用这些名称最终会导致臭代码。

我有一篇博文,介绍了一种很好的财产变更通知方法:BooleanToVisibilityConverter

为了说清楚,我建议你摆脱关于IOKandCancelButtonsVM接口的任何想法,一定要包括基本视图模型上的简单布尔属性,这些属性将被许多其他视图模型扩展。使用确定/取消按钮绑定到对话框。

要在文本中对此进行图表,它将如下所示:

  

YourBaseVm < - BaseVmUsedByDialogs < - SpecificDialogVm

(注意斜体表示该类是抽象的)

答案 1 :(得分:1)

看来你已经有了一个基本的viewmodel类。只需在那里添加两个属性。您可能希望创建继承自第一个的第二个基础,当需要这两个属性时使用它们,因此如果不是,则没有开销。

答案 2 :(得分:1)

为什么不在基类BaseVM中使用virtual properties,并在其中实现默认功能。如果其他派生类想要扩展它,它们总是可以根据所需的功能覆盖它。

确保您的BaseVM正在实施INotifyPropertyChanged

答案 3 :(得分:0)

我只是创建一个抽象基类,并让ViewModel需要从中继承这些属性。保持简单。

abstract class BaseDialogVM : BaseVM
{
    private Visibility _OkButtonVisibility;
    public Visibility OkButtonVisibility {
        get { return _OkButtonVisibility; }
        set { 
           _OkButtonVisibility = value;
           RaisePropertyChanged("OkButtonVisibility");
        }
    }

    private Visibility _CancelButtonVisibility;
    public Visibility CancelButtonVisibility {
        get { return _CancelButtonVisibility; }
        set { 
           _CancelButtonVisibility = value;
           RaisePropertyChanged("CancelButtonVisibility");
        }
    }
}

class VM1 : BaseDialogVM { /*...*/ }