2011-07-25 10 views
5

Estoy fusionando dos ejemplos encontrados en Internet. Uno sobre stretched selection styles y otro sobre multi-selection in a treeview.Obtiene el padre de TreeViewItem en HierarchicalDataTemplate en WPF

Tengo todo funcionando, excepto las muescas de la vista de árbol. Podría dar todo mi código, pero eso no lo resolvería.

Mi problema radica en el siguiente método:

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

Este método intenta recuperar la profundidad de un TreeViewItem en el árbol. El problema es: elem.Parent es siempre nulo. Lo que resulta en profundidades de 0.

Creo que esto está sucediendo, porque estoy usando un HierarchicalDataTemplate. Una parte de mi xaml se ve así.

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

El XAML para mi estilo de la vista de árbol se parece a esto:

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

¿Cómo puedo hacer que el HierarchicalDataTemplate llenar la propiedad Parent?

Respuesta

7

Me gustaría escanear el árbol visual en su lugar.

Aquí es una solución simple (aunque no tan elegante):

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

Saludos.

+0

He visto este. Pero ¿cómo es que, cuando normalmente agrego 'TreeViewItem's al árbol, * hay * una relación padre/hijo? – Marnix

+0

Aquí hay otra publicación que responde acerca de la propiedad Parent dentro de una DataTemplate: http://stackoverflow.com/questions/3255365/wpf-binding-parent-property-in-hierarchicaldatatemplate Sin embargo, incluso el escaneo del árbol visual es * NO * la mejor manera. La forma más confiable es obtener la profundidad del modelo, simplemente porque el árbol es una representación visual de un modelo jerárquico. El árbol visual no puede ser confiable. Por ejemplo, piense en una vista filtrada de su jerarquía: los cambios visuales, pero la profundidad se mantiene igual. –

+0

Sí, parece más fácil ponerlo en el modelo, pero ¿cómo puedo especificarlo en mi Estilo? Mi primer tutorial al que hago referencia reemplaza el estilo predeterminado de una vista en árbol. ¿Cómo se puede usar el modelo dentro de un estilo? – Marnix

Cuestiones relacionadas