В чем разница между DataTemplate и DataContext в WPF? - PullRequest
5 голосов
/ 09 марта 2010

Я могу установить связь между моделью представления и представлением с помощью следующего синтаксиса DataContext:

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

И я также могу установить связь между моделью представления и представлением с помощью следующего синтаксиса DataTemplate:

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

В чем разница между двумя? Второй XAML не устанавливает контекст данных представления?

Ответы [ 2 ]

8 голосов
/ 09 марта 2010

Ваш второй 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 будут отображаться одинаково, но второе легче использовать повторно. (Например, вам нужно изменить привязку только в одном месте, если вы хотите отобразить другую дату.)

2 голосов
/ 09 марта 2010

DataContext из FrameworkElement - это то, с чем связан элемент. Это в основном типа object. В шаблоне MVVM это чаще всего объект ViewModel, но это не обязательно. Это просто некоторая контекстная информация, которую вы хотите применить к этому FrameworkElement. Само по себе это не влияет напрямую на визуальное представление.

Когда WPF хочет отобразить некоторый объект, который не имеет своего собственного визуального представления (например, не является потомком UIElement), он посмотрит, существует ли соответствующий DataTemplate, чтобы определить, как он должен представлять эти данные В вашем примере вы сказали, что класс UserViewModel должен быть представлен с использованием элемента управления UserView, но вы на самом деле не создали ни UserViewModel, ни UserView.

Эти два понятия часто идут вместе. Например, представьте, что у вас есть ObservableCollection<object>, в котором есть Foo и Bar объект. Вы можете определить различные DataTemplate s для Foo и Bar. Тогда вы можете связать свою коллекцию в ItemsControl. Каждый объект в элементе управления получит визуальное представление на основе соответствующего DataTemplate от его типа.

Еще один простой пример: если у вас в свой ViewModel есть свойство с именем DisplayObject, и вы просто хотите, чтобы оно отображалось с указанным вами DataTemplate, вы можете использовать элемент управления ContentPresenter:

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

Опять же, это приводит к тому, что WPF ищет правильный шаблон для типа и использует его для построения представления.

...