【问题标题】:Get TreeViewItem's parent in HierarchicalDataTemplate in WPF在 WPF 中的 HierarchicalDataTemplate 中获取 TreeViewItem 的父项
【发布时间】:2011-07-25 14:58:17
【问题描述】:

我正在合并在互联网上找到的两个示例。一篇关于stretched selection styles,一篇关于multi-selection in a treeview

除了树形视图的缩进之外,我一切正常。我可以给出我所有的代码,但这并不能解决问题。

我的问题在于以下方法:

public static class TreeViewItemExtensions
{
    public static int GetDepth(this TreeViewItem item)
    {
        FrameworkElement elem = item;
        while (elem.Parent != null)
        {
            var tvi = elem.Parent as TreeViewItem;
            if (tvi != null)
                return tvi.GetDepth() + 1;
            elem = elem.Parent as FrameworkElement;
        }
        return 0;
    }
}

此方法尝试检索树中 treeviewItem 的深度。问题是:elem.Parent 总是 null。这导致深度为 0。

我认为这正在发生,因为我使用的是HierarchicalDataTemplate。我的 xaml 的一部分看起来像这样。

<TreeView Name="folderTree"
          ItemsSource="{Binding Folders}"
          SelectedItemChanged="folderTree_SelectedItemChanged"
          HorizontalContentAlignment="Stretch">

    <TreeView.ItemTemplate>
        <HierarchicalDataTemplate ItemsSource="{Binding Folders}"
                                  DataType="{x:Type Model:IFolder}">

            <StackPanel Orientation="Horizontal">
                <StackPanel.Style>
                    <Style TargetType="{x:Type StackPanel}">
                        <Style.Triggers>
                            <DataTrigger Binding="{Binding IsSelected}"
                                         Value="True">
                                <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
                            </DataTrigger>
                        </Style.Triggers>
                    </Style>
                </StackPanel.Style>

                <Image Source="{Binding Converter={StaticResource iconConverter}}" Height="{Binding ElementName=theFile,Path=ActualHeight}"/>
                <TextBlock Text="{Binding FileName}" Name="theFile"/>
            </StackPanel>
        </HierarchicalDataTemplate>
    </TreeView.ItemTemplate>
</TreeView>

我的树视图样式的 XAML 如下所示:

<Style x:Key="{x:Type TreeViewItem}" TargetType="{x:Type TreeViewItem}">

    <!-- leaving some stuff out here -->

    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type TreeViewItem}">

                <ControlTemplate.Resources>
                    <local:LeftMarginMultiplierConverter Length="19" x:Key="lengthConverter" />
                </ControlTemplate.Resources>

                <StackPanel>
                    <!-- The upper part of the TreeViewItem -->
                    <Border Name="Bd" 
                            Background="{TemplateBinding Background}"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}"
                            Padding="{TemplateBinding Padding}">

                        <!-- The margin is what we try to measure, how can we get the parents from the templatedParents? -->
                        <Grid Margin="{Binding Converter={StaticResource lengthConverter}, 
                                               RelativeSource={RelativeSource TemplatedParent}, 
                                               Path=.}">

                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="19" />
                                <ColumnDefinition />
                            </Grid.ColumnDefinitions>

                            <ToggleButton x:Name="Expander" 
                                          Style="{StaticResource ExpandCollapseToggleStyle}"
                                          IsChecked="{Binding Path=IsExpanded, 
                                                      RelativeSource={RelativeSource TemplatedParent}}"
                                          ClickMode="Press"/>

                            <ContentPresenter x:Name="PART_Header"
                                              Grid.Column="1"
                                              ContentSource="Header"
                                              HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"/>
                        </Grid>
                    </Border>

                    <!-- the children of the TreeViewItem -->
                    <ItemsPresenter x:Name="ItemsHost" />
                </StackPanel>

                <!-- leaving some stuff out here with triggers -->

            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

如何让 HierarchicalDataTemplate 填充 Parent 属性?

【问题讨论】:

    标签: c# wpf xaml treeviewitem


    【解决方案1】:

    我会扫描可视化树。

    这是一个简单(甚至不那么优雅)的解决方案:

    public static class TreeViewItemExtensions
    {
        public static int GetDepth(this TreeViewItem item)
        {
            DependencyObject target = item;
            var depth = 0;
            while (target != null)
            {
                if (target is TreeView)
                    return depth;
                if (target is TreeViewItem)
                    depth++;
    
                target = VisualTreeHelper.GetParent(target);
            }
            return 0;
        }
    }
    

    干杯。

    【讨论】:

    • 我看过这个。但是,当我通常将TreeViewItems 添加到树时,为什么会有 父/子关系?
    • 这是另一篇关于 DataTemplate 中 Parent 属性的回答:stackoverflow.com/questions/3255365/… 然而,即使是可视化树的扫描也不是最好的方法。最可靠的方法是从模型中获取深度,因为树是层次模型的可视化表示。视觉树是不可靠的。例如,考虑一下层次结构的过滤视图:视觉变化,但深度保持不变。
    • 是的,将它放入模型中似乎更容易,但我如何在我的样式中指定它?我参考的第一个教程覆盖了树视图的默认样式。如何在样式中使用模型?
    • 对不起,我误解了你的目标。逻辑深度应该在模型中计算出来,而视觉深度只能依赖于视觉层。上面的功能不能与引用样本的转换器一起工作吗?
    • 是的,它确实有效,但我只是好奇你将如何在 MVVM 模型中做到这一点。我将针对 treeviewitem 的样式以及需要计算深度的位置发布我的 XAML。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-10-11
    • 1970-01-01
    • 2017-02-08
    • 2016-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多