2013-05-10 11 views
8

Mam TreeView i próbuję wprowadzić styl, który pozwoli mi umieścić obramowanie wokół wszystkich dzieci określonego węzła przy użyciu HierarchicalDataTemplate. Przykładem tego, co chcę, przedstawiono poniżej:Dodaj obramowanie wokół wszystkich dzieci TreeViewItem

enter image description here

Poniższy kod jest co mam tak daleko.

<HierarchicalDataTemplate DataType="{x:Type model:Node}" ItemsSource="{Binding Children, Mode=OneWay}"> 
    <StackPanel> 
      <TextBlock Text="{Binding Name}"/> 
    </StackPanel> 
    <HierarchicalDataTemplate.ItemContainerStyle> 
      <Style TargetType="{x:Type TreeViewItem}"> 
       //what goes in here??? 
      </Style> 
    </HierarchicalDataTemplate.ItemContainerStyle>  
</HierarchicalDataTemplate> 

Co muszę dodać, aby zrealizować moją granicę tak, jak chcę?

Odpowiedz

12

Aby renderować Border wokół gromadzenia dzieci na TreeViewItem musimy zmodyfikować Style dla ItemContainerStyle z TreeView

TreeViewItemStyle domyślnie używa <ItemsPresenter x:Name="ItemsHost" /> do renderowania jego zawartość zabaw. Zawartość

dzieci w domyślnej ItemContainerStyle jest przez

<ItemsPresenter x:Name="ItemsHost" 
       Grid.Row="1" 
       Grid.Column="1" 
       Grid.ColumnSpan="2" /> 

teraz przetestować to miałem kolekcji z bool nazwie Type i po prostu starał się renderować Border kiedy to bool prawda

Tak więc zaktualizowałem ItemsPresenter do Które następnie renderowane następujące

enter image description here

Będziesz oczywiście muszą aktualizować powyższe Wiązania opierać się na własnych sprawach, kiedy chcesz Border renderowane.

W moim przypadku moja zmienna Type została ustawiona na wartość True dla pozycji z "1.1", ponieważ jest to zawartość nagłówka.

+0

postaram swoje rozwiązanie w poniedziałek, kiedy wrócę do pracy. Dzięki za odpowiedź –

+0

Twoje rozwiązanie umieszcza obramowanie wokół każdego drzewa TreeViewItem.To, czego potrzebuję, to obramowanie wokół wszystkich grup TreeviewItems –

+0

@Kazuo, zanim opublikujesz ten obraz, zrozumiałem twoje pytanie, że masz obramowanie wokół każdego przedmiotu. Zaktualizowałem swoją odpowiedź, aby powielić opublikowany obraz. Nadzieję, że pomaga – Viv

2

Wygląda zespół WPF myślał, że nikt nie będzie potrzebował tej funkcji, więc nie zostały one uwzględnione dowolną ramkę wokół ItemsPresenter w TreeViewItem szablonu, więc będziesz musiał zmienić TreeViewItem szablon i dodać ramkę wokół ItemsPresenter.

Możesz wyświetlić domyślną definicję stylu/szablonu w stylu TreeViewItem, pobierając słowniki XAML z motywów WPF. Łącza są dostarczane here.

Powyżej znajduje się pełna XAML roztworu roboczego:

<Window x:Class="WpfApplication.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:model="clr-namespace:WpfApplication"> 

    <Window.DataContext> 
     <x:ArrayExtension Type="{x:Type model:Node}"> 
      <model:Node Name="Root"> 
       <model:Node.Children> 
        <model:Node Name="Child 1" HasChildrenBorder="True"> 
         <model:Node.Children> 
          <model:Node Name="Child 1.1"/> 
          <model:Node Name="Child 1.2"/> 
          <model:Node Name="Child 1.3"/> 
         </model:Node.Children> 
        </model:Node> 
        <model:Node Name="Child 2"/> 
       </model:Node.Children> 
      </model:Node> 
     </x:ArrayExtension> 
    </Window.DataContext> 

    <TreeView ItemsSource="{Binding}"> 

     <TreeView.Resources> 

      <!--This part is extracted from Areo.NormalColor.xaml WPF Theme which you can download from locations explained here: https://stackoverflow.com/questions/4158678/where-can-i-download-microsofts-standard-wpf-themes-from/4158681#4158681--> 
      <PathGeometry x:Key="TreeArrow"> 
       <PathGeometry.Figures> 
        <PathFigureCollection> 
         <PathFigure IsFilled="True" 
            StartPoint="0 0" 
            IsClosed="True"> 
          <PathFigure.Segments> 
           <PathSegmentCollection> 
            <LineSegment Point="0 6"/> 
            <LineSegment Point="6 0"/> 
           </PathSegmentCollection> 
          </PathFigure.Segments> 
         </PathFigure> 
        </PathFigureCollection> 
       </PathGeometry.Figures> 
      </PathGeometry> 

      <Style x:Key="ExpandCollapseToggleStyle" TargetType="{x:Type ToggleButton}"> 
       <Setter Property="Focusable" Value="False"/> 
       <Setter Property="Width" Value="16"/> 
       <Setter Property="Height" Value="16"/> 
       <Setter Property="Template"> 
        <Setter.Value> 
         <ControlTemplate TargetType="{x:Type ToggleButton}"> 
          <Border Width="16" 
            Height="16" 
            Background="Transparent" 
            Padding="5,5,5,5"> 
           <Path x:Name="ExpandPath" 
             Fill="Transparent" 
             Stroke="#FF989898" 
             Data="{StaticResource TreeArrow}"> 
            <Path.RenderTransform> 
             <RotateTransform 
              Angle="135" 
              CenterX="3" 
              CenterY="3"/> 
            </Path.RenderTransform> 
           </Path> 
          </Border> 
          <ControlTemplate.Triggers> 
           <Trigger Property="IsMouseOver" Value="True"> 
            <Setter TargetName="ExpandPath" Property="Stroke" Value="#FF1BBBFA"/> 
            <Setter TargetName="ExpandPath" Property="Fill" Value="Transparent"/> 
           </Trigger> 
           <Trigger Property="IsChecked" Value="True"> 
            <Setter TargetName="ExpandPath" Property="RenderTransform"> 
             <Setter.Value> 
              <RotateTransform 
               Angle="180" 
               CenterX="3" 
               CenterY="3"/> 
             </Setter.Value> 
            </Setter> 
            <Setter TargetName="ExpandPath" Property="Fill" Value="#FF595959"/> 
            <Setter TargetName="ExpandPath" Property="Stroke" Value="#FF262626"/> 
           </Trigger> 
          </ControlTemplate.Triggers> 
         </ControlTemplate> 
        </Setter.Value> 
       </Setter> 
      </Style> 

      <Style TargetType="{x:Type TreeViewItem}" BasedOn="{StaticResource {x:Type TreeViewItem}}"> 
       <Setter Property="Template"> 
        <Setter.Value> 
         <ControlTemplate TargetType="{x:Type TreeViewItem}"> 
          <Grid> 
           <Grid.ColumnDefinitions> 
            <ColumnDefinition MinWidth="19" Width="Auto"/> 
            <ColumnDefinition Width="Auto"/> 
            <ColumnDefinition Width="Auto"/> 
           </Grid.ColumnDefinitions> 
           <Grid.RowDefinitions> 
            <RowDefinition Height="Auto"/> 
            <RowDefinition/> 
           </Grid.RowDefinitions> 
           <ToggleButton x:Name="Expander" 
               Style="{StaticResource ExpandCollapseToggleStyle}" 
               IsChecked="{Binding Path=IsExpanded, RelativeSource={RelativeSource TemplatedParent}}" 
               ClickMode="Press"/> 
           <Border Name="Bd" 
             Grid.Column="1" 
             Background="{TemplateBinding Background}" 
             BorderBrush="{TemplateBinding BorderBrush}" 
             BorderThickness="{TemplateBinding BorderThickness}" 
             Padding="{TemplateBinding Padding}" 
             SnapsToDevicePixels="True"> 
            <ContentPresenter x:Name="PART_Header" 
                 ContentSource="Header" 
                 HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 
                 SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/> 
           </Border> 
           <Border Name="ItemsHostBd" 
             Grid.Row="1" 
             Grid.Column="1" 
             Grid.ColumnSpan="2"> 
            <ItemsPresenter x:Name="ItemsHost"/> 
           </Border> 
          </Grid> 
          <ControlTemplate.Triggers> 
           <Trigger Property="IsExpanded" Value="False"> 
            <Setter TargetName="ItemsHostBd" Property="Visibility" Value="Collapsed"/> 
           </Trigger> 
           <Trigger Property="HasItems" Value="False"> 
            <Setter TargetName="Expander" Property="Visibility" Value="Hidden"/> 
           </Trigger> 
           <Trigger Property="IsSelected" Value="True"> 
            <Setter TargetName="Bd" Property="Background" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/> 
            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}"/> 
           </Trigger> 
           <MultiTrigger> 
            <MultiTrigger.Conditions> 
             <Condition Property="IsSelected" Value="True"/> 
             <Condition Property="IsSelectionActive" Value="False"/> 
            </MultiTrigger.Conditions> 
            <Setter TargetName="Bd" Property="Background" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/> 
            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/> 
           </MultiTrigger> 
           <Trigger Property="IsEnabled" Value="False"> 
            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/> 
           </Trigger> 

           <!-- This part is customized to work with HasChildrenBorder property from data-bound object. --> 
           <DataTrigger Binding="{Binding HasChildrenBorder}" Value="True"> 
            <Setter TargetName="ItemsHostBd" Property="BorderBrush" Value="Red"/> 
            <Setter TargetName="ItemsHostBd" Property="BorderThickness" Value="1"/> 
           </DataTrigger> 

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

      <HierarchicalDataTemplate DataType="{x:Type model:Node}" ItemsSource="{Binding Children}"> 
       <TextBlock Text="{Binding Name}"/> 
      </HierarchicalDataTemplate> 

     </TreeView.Resources> 

    </TreeView> 
</Window> 

Oto jak klasa Node jest zdefiniowana:

using System.Collections.ObjectModel; 

namespace WpfApplication 
{ 
    public class Node 
    { 
     public string Name { get; set; } 
     public ObservableCollection<Node> Children { get; set; } 

     public bool HasChildrenBorder { get; set; } 

     public Node() 
     { 
      this.Children = new ObservableCollection<Node>(); 
     } 
    } 
} 
+0

Dziękuję za odpowiedź, ale nie chcę mieć zajęć zawierają jakiekolwiek dane dotyczące sposobu, w jaki powinny być prezentowane w interfejsie użytkownika. Najlepszym rozwiązaniem w moim przypadku byłby tylko xaml. –

+0

Właściwość HasChildrenBorder została użyta jako przykład do pokazania, że ​​koncepcja działa. Możesz umieścić tam dowolną inną własność, dla której dzieci TreeViewItem powinny być graniczone. Następnie powinieneś po prostu zmienić DataTrigger.Binding w ControlTemplate TreeViewItem. – Stipo

+0

Ach, mój błąd. Dziękuję za Twoją odpowiedź. Znalazłem rozwiązanie mojego problemu przy pomocy innego plakatu. –

Powiązane problemy