首页 > 解决方案 > 绑定到 TreeViewItem 的父 DataContext 但 TreeView 的 DataContext 用于最顶层的项目

问题描述

我有一个TreeView使用单个HierarchicalDataTemplate. TreeViewItem我知道如何在a中绑定到父级的属性HierarchicalDataTemplate

<Button
  Command="{Binding DataContext.RemoveCommand,
            RelativeSource={RelativeSource AncestorLevel=2,
                            AncestorType=TreeViewItem}}"
  CommandParameter="{Binding ElementId}" />

但是,这当然不适用于最顶层的项目,因为没有祖先TreeViewItem- 在这里,我想使用DataContextTreeView本身。如何将命令绑定到树视图最顶层元素的TreeView's ?DataContext如有必要,您可以假设视图模型具有与表示每个树项的分层视图模型同名的属性。

标签: xamldata-bindingtreeviewdatacontext

解决方案


这是我基于 Elmish.WPF 的 SubModelCollection 示例(GitHub 上的存储库)修改后的 MainWindow.xaml,它演示了我认为我是如何解决问题的。正如我在对 OP 的评论中提到的,我遇到了这个解决方案的一个新问题,但我希望它可以在不费力的情况下解决。我有一种感觉,这是一个微不足道的问题。

我的意图是一个 HierarchicalDataTemplate 将用于顶级项目,另一个用于所有其他项目。令我惊讶的是,它看起来实际上可以正确处理数据,并且按钮可以在所有级别上工作,但是 WPF 对正在发生的事情并不满意。当我在其下方添加、删除或移动子节点时,二级节点会在视觉上折叠,并且 VS 中的“输出”窗格有一些要说明的内容:

“System.Windows.Data 错误:4:找不到与引用'RelativeSource FindAncestor,AncestorType='System.Windows.Controls.ItemsControl',AncestorLevel='1''的绑定源。BindingExpression:Path=Horizo​​ntalContentAlignment;DataItem=null;目标元素是'TreeViewItem'(名称='');目标属性是'Horizo​​ntalContentAlignment'(类型'Horizo​​ntalAlignment')“

在介绍 SharedPart 之前,我遇到了同样的错误,所以我认为这不是导致它的原因。

这是 MainWindow.xaml,我修改的唯一文件。

<Window
x:Class="Elmish.WPF.Samples.SubModelCollection.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Single counter" Height="800" Width="1000"
WindowStartupLocation="CenterScreen">
<Window.Resources>
    <DataTemplate x:Key="SharedPart">
        <StackPanel Orientation="Horizontal">
            <TextBlock Text="{Binding CounterId}" Width="250" Margin="10,5,10,5" />
            <TextBlock Text="{Binding CounterValue, StringFormat='Counter value: {0}'}" Width="100" Margin="0,5,10,5" />
            <Button Command="{Binding Decrement}" Content="-" Margin="0,5,10,5" Width="30" />
            <Button Command="{Binding Increment}" Content="+" Margin="0,5,10,5" Width="30" />
            <Button Command="{Binding Reset}" Content="Reset" Margin="0,5,10,5" Width="50" />
            <TextBlock Text="{Binding StepSize, StringFormat='Step size: {0}'}" Margin="0,5,10,5" />
            <Slider Value="{Binding StepSize}" TickFrequency="1" Maximum="10" Minimum="1" IsSnapToTickEnabled="True" Width="100" Margin="0,5,10,5" />
            <Button Command="{Binding AddChild}" Content="Add child" Margin="0,5,10,5" />
        </StackPanel>
    </DataTemplate>
    <HierarchicalDataTemplate x:Key="Level2Data" ItemsSource="{Binding Path=ChildCounters}">
        <StackPanel Orientation="Horizontal">
            <ContentPresenter Content="{Binding}" ContentTemplate="{StaticResource SharedPart}"/>
            <Button
                        Command="{Binding DataContext.Remove, RelativeSource={RelativeSource AncestorType={x:Type TreeViewItem}, AncestorLevel=2}}"
                        CommandParameter="{Binding CounterId}"
                        Content="×" Margin="0,5,10,5" Width="20" />
            <Button
                        Command="{Binding DataContext.MoveUp, RelativeSource={RelativeSource AncestorType={x:Type TreeViewItem}, AncestorLevel=2}}"
                        CommandParameter="{Binding CounterId}"
                        Content="↑" Margin="0,5,10,5" Width="20" />
            <Button
                        Command="{Binding DataContext.MoveDown, RelativeSource={RelativeSource AncestorType={x:Type TreeViewItem}, AncestorLevel=2}}"
                        CommandParameter="{Binding CounterId}"
                        Content="↓" Margin="0,5,10,5" Width="20"/>
        </StackPanel>
    </HierarchicalDataTemplate>
    <HierarchicalDataTemplate x:Key="Level1Data" ItemsSource="{Binding Path=ChildCounters}" ItemTemplate="{StaticResource Level2Data}">
        <StackPanel Orientation="Horizontal">
            <ContentPresenter Content="{Binding}" ContentTemplate="{StaticResource SharedPart}"/>
            <Button
                        Command="{Binding DataContext.Remove, RelativeSource={RelativeSource FindAncestor, AncestorType=TreeView}}"
                        CommandParameter="{Binding CounterId}"
                        Content="×" Margin="0,5,10,5" Width="20" />
            <Button
                        Command="{Binding DataContext.MoveUp, RelativeSource={RelativeSource FindAncestor, AncestorType=TreeView}}"
                        CommandParameter="{Binding CounterId}"
                        Content="↑" Margin="0,5,10,5" Width="20" />
            <Button
                        Command="{Binding DataContext.MoveDown, RelativeSource={RelativeSource FindAncestor, AncestorType=TreeView}}"
                        CommandParameter="{Binding CounterId}"
                        Content="↓" Margin="0,5,10,5" Width="20"/>
        </StackPanel>
    </HierarchicalDataTemplate>
</Window.Resources>
<StackPanel Margin="0,20,0,10">
    <Button Command="{Binding AddCounter}" Content="Add counter" Width="150" Margin="0,0,0,20" />
    <TreeView ItemsSource="{Binding Counters}" ItemTemplate="{StaticResource Level1Data}">
    </TreeView>
</StackPanel>


推荐阅读