Получить родительский элемент TreeViewItem в HierarchicalDataTemplate в WPF - PullRequest
5 голосов
/ 25 июля 2011

Я объединяю два примера, найденных в интернете. Один о растянутых стилях выделения и один о мульти-выделении в виде дерева .

У меня все работает, кроме отступов в виде дерева. Я мог бы дать весь свой код, но это не решило бы его.

Моя проблема заключается в следующем методе:

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?

1 Ответ

7 голосов
/ 25 июля 2011

Вместо этого я бы сканировал визуальное дерево.

Вот простое (даже не очень элегантное) решение:

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;
    }
}

Приветствие.

...