问题描述
人们DataTemplates
想根据viewmodel动态切换视图时使用这种方式:
<Window>
<Window.Resources>
<DataTemplate DataType="{x:Type local:VM1}">
<!-- View 1 Here -->
</DataTemplate>
<DataTemplate DataType="{x:Type local:VM2}">
<!-- View 2 here -->
</DataTemplate>
</Window.Resources>
<ContentPresenter Content="{Binding}"/>
</Window>
所以,
如果Window.DataContext
是的实例VM1
,View1
则将显示,
而如果
Window.DataContext
是的实例VM2
,View2
则将显示。
当然,如果只需要1个View且永不更改,则毫无意义。
解决方法
为什么这个?
MainWindow.xaml:
<Window x:Class="MVVMProject.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<ContentControl Content="{Binding}"/>
</Grid>
</Window>
将您的ExampleView.xaml设置为:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vms="clr-namespace:MVVMProject.ViewModels">
<DataTemplate DataType="{x:Type vms:ExampleVM}" >
<Grid>
<ActualContent/>
</Grid>
</DataTemplate>
</ResourceDictionary>
并创建如下窗口:
public partial class App : Application {
protected override void OnStartup(StartupEventArgs e) {
base.OnStartup(e);
MainWindow app = new MainWindow();
ExampleVM context = new ExampleVM();
app.DataContext = context;
app.Show();
}
}
什么时候可以这样做?
App.xaml :(设置启动窗口/视图)
<Application x:Class="MVVMProject.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="ExampleView.xaml">
</Application>
ExampleView.xaml :(不是ResourceDictionary的窗口)
<Window x:Class="MVVMProject.ExampleView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vms="clr-namespace:MVVMProject.ViewModels">
>
<Window.DataContext>
<vms:ExampleVM />
</Window.DataContext>
<Grid>
<ActualContent/>
</Grid>
</Window>
从本质上讲,它是 “作为数据模板查看”(VaD)与“作为窗口查看”(VaW)
这是我对比较的理解:
- VaD:让您在不关闭窗口的情况下切换视图。(这对于我的项目而言是不可取的)
- VaD:VM对View绝对一无所知,而在VaW中(仅)它必须能够在打开另一个窗口时实例化它
- VaW:我实际上可以在Designer中看到我的xaml渲染(至少在当前设置中,我无法使用VaD)
- VaW:直观地与打开和关闭窗口一起工作;每个窗口都有一个对应的View(和ViewModel)
- VaD:ViewModel可以通过属性传递初始窗口的宽度,高度,可缩放性等(而在VaW中,它们直接在Window中设置)
- VaW:可以设置FocusManager.FocusedElement(不确定VaD中的方式)
- VaW:文件较少,因为我的窗口类型(例如功能区,对话框)已合并到其视图中
那么这是怎么回事?我不能只在XAML中构建窗口,通过VM的属性干净地访问其数据并完成操作吗?后面的代码是相同的(几乎为零)。
我正在努力理解为什么我应该将所有View内容改组为ResourceDictionary。