我可以通过以下DataContext
语法设置View Model和view之间的关系:
<UserControl.DataContext>
<view_model:MainMenuModel />
</UserControl.DataContext>
我还可以通过以下DataTemplate
语法设置View Model和view之间的关系:
<DataTemplate
DataType="{x:Type viewModel:UserViewModel}">
<view:UserView />
</DataTemplate>
两者有什么区别?第二个XAML是否未设置视图的数据上下文?
答案 0 :(得分:8)
您的第二个XAML定义了一个模板,可用于显示viewModel:UserViewModel
类型的对象。它不会为任何内容设置数据,但如果要求ContentPresenter
显示该类型的对象,它将使用您的模板。
您的第一个XAML正在设置控件的DataContext
属性。它定义您在该范围内执行的任何绑定都将使用DataContext
作为绑定的根(除非明确覆盖)。有关DataContext
工作的简单示例,请比较这两个(都假设“s”是System
命名空间):
<StackPanel>
<TextBlock Text="{Binding Day, Source={x:Static s:DateTime.Now}}" />
<TextBlock Text="{Binding Month, Source={x:Static s:DateTime.Now}}" />
<TextBlock Text="{Binding Year, Source={x:Static s:DateTime.Now}}" />
</StackPanel>
<StackPanel DataContext="{Binding Source={x:Static s:DateTime.Now}}">
<TextBlock Text="{Binding Day}" />
<TextBlock Text="{Binding Month}" />
<TextBlock Text="{Binding Year}" />
</StackPanel>
两个StackPanels
将呈现相同的内容,但第二个更容易重用。 (例如:如果你想显示不同的日期,你只需要在一个地方更改装订。)
答案 1 :(得分:2)
DataContext
的{{1}}是元素绑定的内容。它基本上是FrameworkElement
类型。在MVVM模式中,这通常是ViewModel对象,但它不一定是。它只是您想要应用于object
的一些上下文信息。它本身并不直接影响视觉表现。
当WPF想要显示一些没有自己的可视化表示的对象时(例如,不是FrameworkElement
的后代),它会查看是否存在相应的UIElement
来定义它应该显示该数据。在您的示例中,您已说过应使用DataTemplate
控件显示UserViewModel
类,但您实际上并未创建UserView
或{{1} }。
这两个概念经常在一起。例如,假设您有一个UserViewModel
,其中包含UserView
和ObservableCollection<object>
个对象。您可以为Foo
和Bar
定义不同的DataTemplate
。然后,您可以将您的集合绑定到Foo
。控件中的每个对象都将根据其类型中的相应Bar
获得可视化表示。
另一个简单示例:如果您的ViewModel上有一个名为ItemsControl
的属性,并且您只希望它与您定义的DataTemplate
一起显示,则可以使用DisplayObject
控件:
DataTemplate
同样,这会导致WPF查找该类型的正确模板,并使用它来构造表示。