【问题标题】:WPF: switching UserControls depending on corresponding ViewModels (MVVM)WPF:根据相应的 ViewModel (MVVM) 切换用户控件
【发布时间】:2011-06-28 11:08:54
【问题描述】:

我将尝试通过想象这个例子来简化我正在处理的任务:

假设我们有以下模型类的层次结构:

Animal
   Lion
   Snake
   Bird

...对应的 ViewModel:

AnimalCollectionViewModel
   AnimalViewModel
      LionViewModel
      SnakeViewModel
      BirdViewModel

...以及相应的视图:

AnimalCollectionView
   LionView
   SnakeView
   BirdView

假设 AnimalCollection 包含一个列表,其中填充了不同类型动物的对象,并且在列表下方有一个属性网格,用于设置所选动物的属性。显然,属性网格将具有不同的属性,并且应该在所选项目的类型发生变化时发生变化。

问题是:如何根据MVVM模式实现WPF中属性网格的切换?使用什么机制?

目前,我在基本 ViewModel (AnimalViewModel.PropertyGridType = {Lion, Snake, Bird}) 中有一个抽象枚举属性,派生类通过返回相应的值来实现该属性。 AnimalCollectionView 会根据此属性的值更改属性网格用户控件。像这样的:

...

<UserControl.Resources>
    <Style x:Key="PropertyGridStyle" TargetType="ContentControl">
        <Style.Triggers>
            <DataTrigger Binding="{Binding PropertyGridType}" Value="Lion">
                <Setter Property="Content">
                    <Setter.Value>
                        <view:LionPropertyGridView />
                    </Setter.Value>
                </Setter>
            </DataTrigger>
            <DataTrigger Binding="{Binding PropertyGridType}" Value="Snake">
                <Setter Property="Content">
                    <Setter.Value>
                        <view:SnakePropertyGridView />
                    </Setter.Value>
                </Setter>
            </DataTrigger>
        </Style.Triggers>
    </Style>
</UserControl.Resources>

<ContentControl Style="{StaticResource PropertyGridStyle}" />

...

但我不确定这是否是正确的方法。 (至少我不喜欢引入辅助枚举属性。是否可以根据 ViewModel 类型推导出必要的用户控件?) 有人可以建议其他选择吗? 提前致谢!

【问题讨论】:

  • 只要您的视图逻辑与视图分离并使用数据绑定,您就可以轻松地在 mvvm 领域。这样做的主要好处之一是可测试性,所以从一个用例和一些测试开始。然后,您可以根据需要应用不同的 OOP 和 wpf 技术。干杯

标签: wpf mvvm


【解决方案1】:

是否可以根据 ViewModel 类型推导出必要的用户控件?

你是说,像这样?

<Window.Resources>
   <DataTemplate DataType="{x:Type vm:LionViewModel}">
      <v:LionView />
   </DataTemplate>
   <DataTemplate DataType="{x:Type vm:SnakeViewModel}">
      <v:SnakeView />
   </DataTemplate>
   <DataTemplate DataType="{x:Type vm:BirdViewModel}">
      <v:BirdView/>
   </DataTemplate>
</Window.Resources>

请参阅Josh Smith's article on MVVM 中的“将视图应用于视图模型”。

编辑:

这是一个基于类型的模板选择的简单示例,您可以将其粘贴到 Kaxaml 中以向自己证明它确实有效:

<Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:sys="clr-namespace:System;assembly=mscorlib">
  <Page.Resources>
    <sys:String x:Key="string">this is a string</sys:String>
    <sys:Int32 x:Key="int32">1234</sys:Int32>
    <DataTemplate DataType="{x:Type sys:String}">
      <TextBlock Foreground="Red" Text="{Binding}"/>
    </DataTemplate>
    <DataTemplate DataType="{x:Type sys:Int32}">
      <TextBlock Foreground="Blue" Text="{Binding}"/>
    </DataTemplate>
  </Page.Resources>
  <StackPanel>  
    <ContentControl Content="{Binding Source={StaticResource string}}"/>
    <ContentControl Content="{Binding Source={StaticResource int32}}"/>
  </StackPanel>
</Page>

【讨论】:

  • 我几乎可以肯定这正是我的意思:)) 谢谢你,罗伯特
  • 基于类型的模板选择是我最喜欢的 WPF 功能。了解它的所有含义是促使我进入 WPF 学习曲线的识别我的施虐者阶段的原因。
  • 您可以在项目控件或内容控件中使用它们。例如,&lt;ContentControl Content="{Binding X}"/&gt; 创建一个ContentPresenter,其中包含与X 的类型匹配的任何数据模板,就像&lt;ItemsControl ItemsSource="{Binding X}"/&gt; 创建一个充满ItemsPresenters 的面板一样。 (通常,任何带有ItemsSource 属性的东西都是项目控件;任何带有Content 属性的东西都是内容控件。)`
  • 好吧,如果没有更多信息,我无法告诉你你做错了什么,但我可以告诉你它应该可以工作 - 检查我对我的评论所做的编辑以获得一个快速测试用例你可以粘贴到 Kaxaml 中。
  • 你在正确的轨道上。在实践中,您通常会在集合视图模型中创建一个SelectedItem 属性 - 例如,如果您正在实现命令 - 并将列表框中的选定项和内容控件的内容绑定到该属性.要直接绑定到控件,请使用{Binding ElementName=foo, Path=SelectedItem}。如果这不起作用,请将一些文字内容放入控件中并确保其可见 - 当真正的问题是布局之一时,我已经花费了大量时间来排除功能完美的绑定。
【解决方案2】:

您可以为此使用DataTemplateSelector。选择正确模板的方法取决于您。如果您愿意,可以使用枚举或测试类类型。

【讨论】:

  • 谢谢你,Goran,我去看看
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-08-29
  • 2013-07-04
  • 2016-04-04
  • 1970-01-01
  • 2011-03-21
  • 1970-01-01
  • 2016-08-08
相关资源
最近更新 更多