为UserControls创建VM时,谁应该创建和设置VM?

时间:2012-11-08 14:46:23

标签: wpf mvvm

我对如何在MVVM中布局我的代码感到有点困惑 - 如果我有一个带有相应VM类的UserControl,其他控件应该如何使用我的UserControl?

如果消费者直接绑定到VM,或者我应该只复制这些属性的子集,我想实际用作UserControl的DependencyProperties吗?

就此而言,应该将UserControl的VM注入到UserControl的代码隐藏中,还是应该使用此UserControl的任何控件的VM将其作为依赖项包含在内并将其绑定到UserControl?

为了说清楚:假设我在UserControl中有一个ListBox,并在已经用MVVM实现的Window中使用它。但我对UserControl VM的实现和相应的绑定感到困惑。

我认为理想的解决方案是通过UserControl中的依赖属性公开ListBox的SelectedItems,然后使用UserControl的Window将绑定到这些。

或者Window的VM是否应该将VM作为属性引用,是否将其注入并直接绑定到该属性上?

依赖项属性是仅在UserControls中定义还是可以/应该在VM中定义?

我认为Window会在窗口的XAML中通过

进行绑定
{Binding ElementName=myUserControl, Path=SelectedItems}

{Binding Path=MyViewModel.SelectedItems} 

通过前者做这件事似乎更有意义,因为后者要求View了解另一个VM?

2 个答案:

答案 0 :(得分:2)

>其他控件应如何使用我的UserControl?

仅通过用户控件上的公开依赖属性。

>消费者应该直接绑定到VM还是应该只复制这些属性的子集?我想实际用作UserControl的DependencyProperties?

每个控件都应该是一个独立的实体,不应该有任何秘密握手(使用或来自)来使用控件。想想你是微软的设计,很多不同的用户都会使用你的控件。所以答案#1就是相关的;想一个独立的实体。

>我认为理想的解决方案是通过UserControl中的依赖项属性公开ListBox的SelectedItems,然后使用UserControl的Window将绑定到这些。

托管控件的窗口将包含一个View Model,其中包含一个Observable数据项列表。这将保存用户控件将通过其依赖属性绑定的数据。把它当作许多消费者的生产者模式。消费者是控制者。控件是否具有VM对于主程序的运行并不重要;每个控件都是自己的岛屿。

答案 1 :(得分:2)

在使用WPF和MVVM时请记住,View图层只是一种用户友好的方式来绘制ModelsViewModels,以及View实际上不是你的申请。您的View实际上必须了解有关数据层的基础知识,以便定义如何绘制数据层。

因此,如果您的应用程序需要显示Items列表并保持SelectedItem,那么应该在ViewModel或Model中,而不是在实际的View层中。

通常对我而言UserControls是以下两件事之一:

  • 可以在没有特定UserControl的任何地方使用的独立DataContext,并且可以针对任何特定于控件的值公开DependencyProperties。示例包括Calendar控件或Popup控件

    <local:MyUserControl Items="{Binding SomeItemList}" 
                         SelectedItem="{Binding SomeItem}" />
    
  • 或者它们是UserControl,仅适用于特定的ViewModel。这对我来说更为常见。 ViewModel是数据层中的某个属性,我通常在应用程序的某个地方有一个隐式DataTemplate,告诉WPF在需要呈现特定UserControl时的任何时候使用ViewModel < / p>

    <DataTemplate DataType="{x:Type local:SomeViewModel}">
        <local:MyUserControl />
    </DataTemplate>
    
    <ContentPresenter Content="{Binding SomeViewModelProperty}" />
    

此外,您在任何时候都不应在DataContext内部设置UserControl的{​​{1}},因为UI图层仅用于表示数据层的UI (您的UserControl / Models),并通过设置ViewModels内部的数据层,以便UserControl无法用于绘制任何其他数据对象