我将通过想象这个例子来尝试简化我正在进行的任务:
假设我们有以下模型类层次结构:
Animal
Lion
Snake
Bird
Run Code Online (Sandbox Code Playgroud)
...对应的ViewModels:
AnimalCollectionViewModel
AnimalViewModel
LionViewModel
SnakeViewModel
BirdViewModel
Run Code Online (Sandbox Code Playgroud)
......和相应的观点:
AnimalCollectionView
LionView
SnakeView
BirdView
Run Code Online (Sandbox Code Playgroud)
假设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}" />
Run Code Online (Sandbox Code Playgroud)
...
但我不确定这是否是正确的做法.(至少我不喜欢引入辅助枚举属性.是否可以根据ViewModel类型推断出必要的用户控件?)任何人都可以建议其他选项吗?提前致谢!
Rob*_*ney 22
是否可以基于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>
Run Code Online (Sandbox Code Playgroud)
请参阅Josh Smith关于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>
Run Code Online (Sandbox Code Playgroud)