Views中包含Views时,DataContext是如何继承的?

4

我正在重新构建Josh Smith的WPF CommandSink示例,但有一些关于他的数据绑定的事情我不理解,特别是当一个视图嵌套在另一个视图内并且它们都在一个具有数据上下文的窗口中时,数据上下文是如何继承的。

  • 所有的数据绑定都在XAML文件中声明,在窗口或两个视图之间没有任何代码(很好)
  • 顶层窗口将其数据上下文定义为CommunityViewModel,并简单地显示CommunityView
  • 问题:那么现在在CommunityViewModel中,jas:CommandSinkBinding.CommandSink="{Binding}"实际上是做什么?“CommandSink”是一个附加属性,所以这是将来自DemoWindow的继承绑定作为名为“CommandSink”的附加属性的值“附加”到CommandSinkBinding对象上吗?

  • 问题:此外,PersonView似乎没有数据上下文,但它却有像<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
如果您设置ItemsSource,那么该控件中的项的DataContext直接映射到ItemsSource中的项。

这解决了我遇到的问题。我在ItemsControl.ItemTemplate中显式设置子项的DataContext,但它会被设置为null。谢谢! - hitec

3

如果没有为控件明确指定数据上下文,那么该控件将继承其父级的数据上下文。因此,回答您的第二个问题是肯定的。


1

PersonView是由CommunityView(CommunityView.xaml:16)中ItemsControl的DataTemplate生成的。

DataTemplates会自动将其可视化元素的DataContext分配给模板显示的数据。这就是WPF的工作原理。

CommunityView的DataContext是通过从Window继承设置的。

附加的命令接收器属性会在具有附加属性赋值的对象的CommandBindings属性中包含的所有CommandSinkBinding对象上设置实例CommandSink属性。因此,在CommunityView.xaml中,CommunityView(KillAll)中所有CommandSinkBindings的CommandSink都通过绑定设置为视图的DataContext。

CommandSink属性用于调用适当目标(在本例中为ViewModel)上的Execute和CanExecute函数。


0

DataContext是FrameworkElement(所有WPF控件的基类)上的一个属性,它被实现为DependencyProperty。这意味着逻辑树中的所有后代元素共享相同的DataContext。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接