Как DataContext наследуется в представлениях, которые содержат представления? - PullRequest
3 голосов
/ 22 апреля 2009

Я перестраиваю Пример WPF CommandSink Джоша Смита и есть несколько вещей, которые я не понимаю в его привязке данных, особенно о том, как наследуется текст данных, когда представление содержится в другом представлении, которое является содержится в окне с текстом данных.

  • вся привязка данных объявлена ​​в файлах XAML, за окном или одним из представлений абсолютно нет кода (хорошо)
  • верхнее окно определяет свой DataContext как CommunityViewModel и просто отображает CommunityView
  • Вопрос: так что теперь в CommunityViewModel, что на самом деле делает jas:CommandSinkBinding.CommandSink="{Binding}"? «CommandSink» является вложенным свойством, и является ли это «присоединением» унаследованной привязки, которая поступает из DemoWindow в качестве значения присоединенного свойства «CommandSink» для объекта CommandSinkBinding?

  • Вопрос: Кроме того, PersonView, похоже, не имеет DataContext, но в нем есть такие строки, как <TextBlock Text="{Binding Name}" Width="60" />, которые предполагают, что привязка установлена. Таким образом, PersonView автоматически получает свою привязку из строки в CommunityView ItemsSource="{Binding People}"?

Спасибо за любые разъяснения здесь.

DemoWindow.xaml:

<Window 
  x:Class="VMCommanding.DemoWindow"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:view="clr-namespace:VMCommanding.View"
  xmlns:vm="clr-namespace:VMCommanding.ViewModel"
  FontSize="13"
  ResizeMode="NoResize"
  SizeToContent="WidthAndHeight" 
  Title="ViewModel Commanding Demo"   
  WindowStartupLocation="CenterScreen"
  >
  <Window.DataContext>
    <vm:CommunityViewModel />
  </Window.DataContext>

  <Window.Content>
    <view:CommunityView />
  </Window.Content>
</Window>

CommunityView.xaml:

<UserControl 
  x:Class="VMCommanding.View.CommunityView"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:jas="clr-namespace:VMCommanding"
  xmlns:view="clr-namespace:VMCommanding.View"
  xmlns:vm="clr-namespace:VMCommanding.ViewModel"  
  jas:CommandSinkBinding.CommandSink="{Binding}"
  >
    <UserControl.CommandBindings>
        <jas:CommandSinkBinding Command="vm:CommunityViewModel.KillAllMembersCommand" />
    </UserControl.CommandBindings>

    <DockPanel Margin="4">
        <ItemsControl
      DockPanel.Dock="Bottom" ItemsSource="{Binding People}">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <view:PersonView />
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
        <Button 
      Command="vm:CommunityViewModel.KillAllMembersCommand"
      Content="Kill All"
      Margin="0,0,0,8"
      />
    </DockPanel>
</UserControl>

PersonView.xml:

<UserControl 
  x:Class="VMCommanding.View.PersonView"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:jas="clr-namespace:VMCommanding"
  xmlns:vm="clr-namespace:VMCommanding.ViewModel"
  jas:CommandSinkBinding.CommandSink="{Binding}"
  >  
  <UserControl.CommandBindings>
    <jas:CommandSinkBinding Command="vm:PersonViewModel.DieCommand" />
    <jas:CommandSinkBinding Command="vm:PersonViewModel.SpeakCommand" />
  </UserControl.CommandBindings>

  <UserControl.Resources>
    <Style TargetType="{x:Type TextBlock}">
      <Setter Property="Margin" Value="0,0,6,0" />
      <Style.Triggers>
        <DataTrigger Binding="{Binding CanDie}" Value="False">
          <Setter Property="Foreground" Value="#88000000" />
        </DataTrigger>
      </Style.Triggers>
    </Style>
  </UserControl.Resources>

  <StackPanel Margin="2" Orientation="Horizontal">
    <TextBlock Text="Name:" FontWeight="Bold" />
    <TextBlock Text="{Binding Name}" Width="60" />
    <TextBlock Text="Age:" FontWeight="Bold" />
    <TextBlock Text="{Binding Age}" Width="40" />
    <Button 
      Command="vm:PersonViewModel.SpeakCommand"
      CommandParameter="Howdy partner!"
      Content="Speak"
      Margin="0,0,6,0"
      Width="60"
      />
    <Button
      Command="vm:PersonViewModel.DieCommand"
      Content="Die"
      Width="60"
      />
  </StackPanel>
</UserControl>

Ответы [ 4 ]

4 голосов
/ 22 апреля 2009

Если вы установите ItemsSource для ItemsControl, DataContexts элементов в этом элементе управления будут напрямую сопоставлены с элементами ItemsSource.

3 голосов
/ 22 апреля 2009

Элемент управления наследует его родительский DataContext, если он не указан явно для элемента управления. Итак, ответ на ваш второй вопрос - да.

1 голос
/ 22 апреля 2009

PersonView создается DataTemplate для ItemsControl в CommunityView (CommunityView.xaml: 16).

DataTemplates автоматически присваивают DataContext своих визуальных элементов данным, отображаемым шаблоном. Вот как работает WPF.

CommunityView получает свой DataContext, установленный по наследству из окна.

Свойство присоединенного приемника команд устанавливает свойство экземпляра CommandSink для всех объектов CommandSinkBinding, содержащихся в свойстве CommandBindings объекта с назначенным ему присоединенным свойством. Таким образом, в CommunityView.xaml для CommandSink всех CommandSinkBindings в CommunityView (KillAll) задано значение DataContext представления через привязку.

Свойство CommandSink используется для вызова функций Execute и CanExecute для соответствующей цели (в данном случае ViewModel).

0 голосов
/ 09 июня 2009

DataContext является свойством FrameworkElement (базовый класс для всех элементов управления WPF) и реализуется как DependencyProperty. Это означает, что все элементы-потомки в логическом дереве совместно используют один и тот же DataContext.

...