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

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

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

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

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

6
Ashish Ashu 9 Мар 2010 в 12:34

2 ответа

Лучший ответ

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

8
Peter Mortensen 9 Мар 2010 в 16:41
Привет, Питер, Бен Спасибо всем за ответ. Мне интересно, могу ли я установить datacontext и datatemplate элемента управления на одну и ту же модель представления?
 – 
Ashish Ashu
9 Мар 2010 в 17:01
@Ashish: вы можете установить DataContext на саму ViewModel, но вы устанавливаете DataTemplate на шаблон, который отображает ViewModel, а не на саму viewmodel.
 – 
Dan Puzey
9 Мар 2010 в 17:21

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

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

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

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

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

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

2
Ben Von Handorf 9 Мар 2010 в 16:26