WPF DataTemplate / DataTemplateSelector - 两个不同视图使用的ViewModel的最佳方法?

时间:2011-04-14 18:03:14

标签: wpf mvvm prism datatemplate datatemplateselector

基本上,我有以下情况:

ViewModel:FooViewModel : BaseViewModelBarViewModel : BaseViewModel
观点:MainViewFooViewBarView

现在我“注入”视图并使用DataContextDataTemplate设置DataTemplateSelector。显然,我的ItemsControl ItemSource绑定到ObservableCollection<BaseViewModel>,其中包含(目前)FooViewModelBarViewModel

的实例

问题是我想介绍一个AlternateFooView我想要使用相同的FooViewModel。我想我会创建另一个DataTemplate并让我的DataTemplateSelector返回它,但是需要有特殊的逻辑来确定要返回哪个DataTemplate(我不能只通过哪个ViewModel),这意味着我必须在BaseViewModel中拥有某种类型的属性或字段。我不知道这是不是一个好主意,因为这似乎是在ViewModel中引入了一个仅用于选择视图的字段/属性。它不会伤害我的单元测试,但是包含一个字段只是为了帮助决定选择哪个UI视图似乎是一种浪费。我认为它不会破坏MVVM,但我很好奇是否还有其他人有更好的想法?我有其他想法,我更不喜欢......

想法#2:
- 将FooViewModel转换为2个不同的FooViewModel扩展的基类(即BaseFooViewModel,FooViewModel,DifferentFooViewModel)。这看起来很愚蠢,因为除了类类型之外,FooViewModel和DifferentFooViewModel之间没有任何区别。

想法#3:
- 只需复制FooViewModel并使其成为FooViewModel2(它将与FooViewModel完全相同)。这似乎比想法#2更糟糕。

<小时/> 示例代码(显然调整):

public abstract class BaseViewModel : NotificationObject
{
    //Common Stuff
}

public abstract MainViewModel : NotificationObject
{
    public MainViewModel()
    {
        MyItems = new ObservableCollection<BaseViewModel>()
        {
            new FooViewModel();
            new BarViewModel();
            new FooViewModel(); //New Item -- I want it to use the DifferentFooView
        }
        //Load items from a DAL later
    }

    public ObservableCollection<BaseViewModel> MyItems { get; set; }

    //Other Stuff
}

<l:MyItemsControl ItemSource={Binding MyItems} ContentTemplateSelector={StaticResource MyTemplateSelector} />

<小时/> 谢谢!

1 个答案:

答案 0 :(得分:4)

我同意krishnaaditya的观点,这个问题实际上归结为根据ViewModel的状态决定使用哪个View。这种类型的逻辑通常放在模板选择器中,效果很好。如果您不想将该逻辑放入模板选择器,请考虑使用我的Routed Template Selection方法将其外部化。这样可以通过使用路由事件轻松委派模板选择逻辑。

您在评论中提出的关于使用DataTrigger的想法也可以使用,但是这会重新引入VM对象上的属性的需要,该属性指示要加载哪个View(您说您不想要)。在我看来,这不一定是坏事。