简体   繁体   English

WPF中的DataTemplate和DataContext有什么区别?

[英]What is the difference between DataTemplate and DataContext in WPF?

I can set the relationship between View Model and view through following DataContext syntax: 我可以通过以下DataContext语法设置View Model和view之间的关系:

 <UserControl.DataContext>
    <view_model:MainMenuModel />
</UserControl.DataContext>

And I can also set the relationship between View Model and view through following DataTemplate syntax: 我还可以通过以下DataTemplate语法设置View Model和view之间的关系:

    <DataTemplate
        DataType="{x:Type viewModel:UserViewModel}">
        <view:UserView />
    </DataTemplate>

What is the difference between the two? 两者有什么区别? Is the second XAML not setting the data context of a view? 第二个XAML是否未设置视图的数据上下文?

Your second XAML defines a template that can be used to display an object of type viewModel:UserViewModel . 您的第二个XAML定义了一个模板 ,可用于显示viewModel:UserViewModel类型的对象viewModel:UserViewModel It doesn't set data for anything but, if a ContentPresenter is asked to display an object of that type, it will use your template. 它不会为任何内容设置数据,但如果要求ContentPresenter显示该类型的对象,它将使用您的模板。

Your first XAML is setting the DataContext property of your control. 您的第一个XAML正在设置控件的DataContext属性。 It defines that any bindings you perform within that scope will use the DataContext as the root of the binding (unless explicitly overriden). 它定义您在该范围内执行的任何绑定都将使用DataContext作为绑定的根(除非明确覆盖)。 For a simple example of DataContext at work, compare these two (both assume that "s" is the System namespace): 有关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>

Both StackPanels will render identically, but the second is more easily reused. 两个StackPanels都会以相同的方式呈现,但第二个更容易重用。 (Eg: you only have to change the binding in one place if you wanted to display a different date.) (例如:如果要显示不同的日期,则只需在一个地方更改绑定。)

The DataContext of a FrameworkElement is what the element is bound to. FrameworkElementDataContext是元素绑定的内容。 It is fundamentally of type object . 它基本上是类型object In the MVVM pattern, this is most frequently the ViewModel object, but it need not be. 在MVVM模式中,这通常是ViewModel对象,但它不一定是。 It is simply some context information you want to apply to that FrameworkElement . 它只是您要应用于FrameworkElement一些上下文信息。 It does not directly affect the visual representation, by itself. 它本身并不直接影响视觉表示。

When WPF wants to display some object that doesn't have it's own visual representation (eg isn't descended from UIElement , it will look to see if a corresponding DataTemplate exists to define how it should present that data. In your example, you have said that the UserViewModel class should be presented using the UserView control, but you have not actually created either the UserViewModel or UserView . 当WPF想要显示一些没有自己的可视化表示的对象时(例如,不是来自UIElement ,它会查看是否存在相应的DataTemplate来定义它应该如何呈现该数据。在你的例子中,你有表示应该使用UserView控件呈现UserViewModel类,但是您实际上没有创建UserViewModelUserView

These two concepts often go together. 这两个概念经常在一起。 For example, imagine you had an ObservableCollection<object> which had in it a Foo and a Bar object. 例如,假设您有一个ObservableCollection<object> ,其中包含一个Foo和一个Bar对象。 You could define different DataTemplate s for Foo and Bar . 您可以为FooBar定义不同的DataTemplate Then you could bind your collection into an ItemsControl . 然后,您可以将您的集合绑定到ItemsControl Each object in the control would get a visual representation based on the appropriate DataTemplate from its type. 控件中的每个对象都将根据其类型中的相应DataTemplate获得可视化表示。

Another simple example: if you have a property on your ViewModel named DisplayObject and you simply want it to appear with whatever DataTemplate you have defined, you can use the ContentPresenter control: 另一个简单示例:如果ViewModel上有一个名为DisplayObject的属性,并且您只希望它与您定义的任何DataTemplate一起出现,则可以使用ContentPresenter控件:

<ContentPresenter DataContext="{Binding DisplayObject}"/>

Again, this results in WPF looking up the correct Template for the type and using that to construct a representation. 同样,这会导致WPF查找该类型的正确模板并使用它来构造表示。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM