如何为子属性的 Style、Setter 和 HierarchicalDataTemplate 设置 DataContext 绑定?

How to set DataContext Binding on Style, Setter and HierarchicalDataTemplate for sub properties?

如果我使用

设置 Window 的 DataContext
public partial class MainWindow : Window
{
    readonly TreeViewViewModel TreeView;
    public MainWindow()
    {
      //...
      this.DataContext = TreeView;
    }       
}

那么下面的 XAML 工作正常

<TreeView x:Name="radTreeView" Grid.Row="1"
                     Margin = "5,5,5,5"
                     ItemsSource = "{Binding FirstGeneration}"
                     Padding = "5"
                     ScrollViewer.HorizontalScrollBarVisibility = "Visible"
                     ScrollViewer.VerticalScrollBarVisibility = "Visible"
                     IsTextSearchEnabled="True" >
    <TreeView.ItemContainerStyle>
        <Style TargetType="TreeViewItem" >
            <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
            <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
        </Style>
    </TreeView.ItemContainerStyle>
    <TreeView.ItemTemplate>
        <HierarchicalDataTemplate ItemsSource="{Binding Children}" >
            <StackPanel Orientation="Horizontal">
                <CheckBox IsChecked="{Binding IsChecked, Mode=TwoWay}"  />
                <TextBlock VerticalAlignment="Center" Text="{Binding Name}" />
            </StackPanel>
        </HierarchicalDataTemplate>
    </TreeView.ItemTemplate>
</TreeView>

但是,我需要 DataContext 是 ViewModel 的 属性,这样 TreeViewViewModel TreeViewMainViewModel mainViewModel 的 属性 并且代码隐藏中的 DataContext 设置为

public partial class MainWindow : Window
{
    private MainViewModel mainViewModel;
    public MainWindow()
    {
      //...
      this.DataContext = this;
    }       
}

我可以使用 DataContext = "{Binding MainViewModel.TreeView}" 使部分绑定工作,但这只适用于主 TreeView 元素而不适用于样式,Setter,没有 DataContext 的 HierarchicalDataTemplate 属性.

如何为所有 XAML TreeView 元素正确设置数据上下文?

以下是我迄今为止尝试过的方法,但只有 ItemsSource = "{Binding FirstGeneration}" 使用正确的数据上下文

<TreeView x:Name="radTreeView" Grid.Row="1"
                     Margin = "5,5,5,5"
                     DataContext = "{Binding MainViewModel.TreeView}"
                     ItemsSource = "{Binding FirstGeneration}"
                     Padding = "5"
                     ScrollViewer.HorizontalScrollBarVisibility = "Visible"
                     ScrollViewer.VerticalScrollBarVisibility = "Visible"
                     IsTextSearchEnabled="True" >
    <TreeView.ItemContainerStyle>
        <Style TargetType="TreeViewItem" >
            <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
            <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
        </Style>
    </TreeView.ItemContainerStyle>
    <TreeView.ItemTemplate>
        <HierarchicalDataTemplate ItemsSource="{Binding Children}" >
            <StackPanel Orientation="Horizontal">
                <CheckBox IsChecked="{Binding IsChecked, Mode=TwoWay}"  />
                <TextBlock VerticalAlignment="Center" Text="{Binding Name}" />
            </StackPanel>
        </HierarchicalDataTemplate>
    </TreeView.ItemTemplate>
</TreeView>

假设 radTreeView 容器的 DataContextMainViewModel 的一个实例,你可以做

<TreeView ... DataContext="{Binding TreeView}" ItemsSource="{Binding FirstGeneration}">

或不改变DataContext

<TreeView ... ItemsSource="{Binding TreeView.FirstGeneration}">