2013-05-10 101 views
8

我有TreeView,我嘗試實現一種樣式,該樣式將允許我使用HierarchicalDataTemplate在特定節點的所有子節點周圍放置邊框。我想要的一個例子如下所示:在TreeViewItem的所有子節點周圍添加邊框

enter image description here

下面的代碼是我到目前爲止所。

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

我需要添加什麼來實現我想要的邊框?

回答

12

爲了使各地的孩子們的集合BorderTreeViewItem我們需要修改Style爲的TreeView

TreeViewItemStyle默認ItemContainerStyle使用<ItemsPresenter x:Name="ItemsHost" />來呈現它的孩子的內容。

兒童在默認ItemContainerStyle內容由

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

現在給測試這個我曾與一個名爲Type布爾集合,只是試圖呈現一個Border當這個布爾是真實的

所以我更新了ItemsPresenter

<Border Grid.Row="1" 
     Grid.Column="1" 
     Grid.ColumnSpan="2" 
     BorderThickness="1"> 
    <Border.Style> 
    <Style TargetType="{x:Type Border}"> 
     <Setter Property="BorderBrush" 
       Value="Transparent" /> 
     <Style.Triggers> 
     <DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, 
             AncestorType={x:Type TreeViewItem}}, 
             Path=DataContext.Type}" 
         Value="True"> 
      <Setter Property="BorderBrush" 
        Value="Red" /> 
     </DataTrigger> 
     </Style.Triggers> 
    </Style> 
    </Border.Style> 
    <ItemsPresenter x:Name="ItemsHost" /> 
</Border> 

然後呈現以下

enter image description here

你當然已經更新上面的綁定是基於你自己的,當你想呈現的Border的情況。

在我的情況下,我的Type變量被設置爲True,因爲它是Header內容,因此帶有「1.1」的Item。

+0

我會嘗試你在週一的解決方案,當我重返工作崗位。感謝您的回答 – 2013-05-11 13:09:16

+0

您的解決方案在每個TreeViewItem周圍放置一個邊框。我需要的是在張貼這張圖片之前圍繞着整個TreeviewItems組的邊框 – 2013-05-13 09:18:48

+0

@Kazuo ye,我明白你的問題是每個項目都有一個邊框。我更新了我的答案以複製您發佈的圖片。希望有助於 – Viv 2013-05-13 10:43:40

2

看起來像WPF團隊認爲,沒有人會需要這個功能,所以他們並沒有包括各地ItemsPresenter任何邊境TreeViewItem模板,所以你將不得不改變TreeViewItem模板,並添加周圍ItemsPresenter邊框。

您可以通過下載WPF主題XAML詞典來查看默認TreeViewItem樣式/模板定義。鏈接提供here

這裏是一個可行的解決方案的完整的XAML:

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

下面是Node類是如何定義的:

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

謝謝你的回答,但我不想讓我的課程包含任何有關如何在UI中呈現的數據。在我的情況下,最好的解決方案是隻有一個xaml。 – 2013-05-20 10:42:51

+0

HasChildrenBorder屬性僅用作示例以顯示該概念有效。你可以在那裏放置TreeViewItem子項應該與其相鄰的任何其他屬性。然後你應該改變TreeViewItem的ControlTemplate中的DataTrigger.Binding。 – Stipo 2013-05-20 14:19:40

+0

啊,我的錯。謝謝你的答案。我在另一張海報的幫助下找到了解決我的問題的方法。 – 2013-05-20 14:23:35