2009-03-20 32 views
59

Nếu tôi đặt Nền TreeViewItem, nó chỉ làm nổi bật tiêu đề. Làm thế nào tôi có thể làm nổi bật toàn bộ dòng?Làm nổi bật toàn bộ dòng TreeViewItem trong WPF

Tôi đã tìm thấy một bài đăng gần như giải quyết một vấn đề http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/b04f73e2-0b10-4d97-a6da-64df2e30c21d/

Nhưng có một số vấn đề: 1. Nó không làm nổi bật toàn bộ dòng 2. Cây có phong cách XP trên Vista. Tôi không thích nó giống như trên Vista, nhưng nếu người dùng thay đổi theme thành XP - nó phải là XP. 3. Vì vậy, nhiều XAML ...

Bất kỳ ý tưởng, những gì tôi nên tìm?

Trả lời

97

Ở đây chúng ta đi, lần thứ ba một nét duyên dáng. Nếu bạn muốn một cái gì đó trông như thế này.

Full Width TreeView

Điều này tốn một chút công việc. Tôi chắc chắn có rất nhiều cách để làm điều này, nhưng phương pháp này sử dụng một chuyển đổi chiều dài và một phương pháp mở rộng TreeViewItem để có được chiều sâu.Cả hai đều được kết hợp chặt chẽ với cây trực quan TreeViewItem, vì vậy nếu bạn bắt đầu rối tung với các mẫu thì bạn có thể gặp khó khăn. Một lần nữa, đây là phần quan trọng, và bên dưới là mã đầy đủ.

<ControlTemplate TargetType="{x:Type TreeViewItem}"> 
    <ControlTemplate.Resources> 
     <local:LeftMarginMultiplierConverter Length="19" x:Key="lengthConverter" /> 
    </ControlTemplate.Resources> 
    <StackPanel> 
     <Border Name="Bd" 
      Background="{TemplateBinding Background}" 
      BorderBrush="{TemplateBinding BorderBrush}" 
      BorderThickness="{TemplateBinding BorderThickness}" 
      Padding="{TemplateBinding Padding}"> 
      <Grid Margin="{Binding Converter={StaticResource lengthConverter}, 
        RelativeSource={RelativeSource TemplatedParent}}"> 

       <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> 
     <ItemsPresenter x:Name="ItemsHost" /> 
    </StackPanel> 
    <!-- Triggers --> 
</ControlTemplate> 

TreeViewDepth mở rộng

public static class TreeViewItemExtensions 
{ 
    public static int GetDepth(this TreeViewItem item) 
    { 
     TreeViewItem parent; 
     while ((parent = GetParent(item)) != null) 
     { 
      return GetDepth(parent) + 1; 
     } 
     return 0; 
    } 

    private static TreeViewItem GetParent(TreeViewItem item) 
    { 
     var parent = VisualTreeHelper.GetParent(item); 
     while (!(parent is TreeViewItem || parent is TreeView)) 
     { 
      parent = VisualTreeHelper.GetParent(parent); 
     } 
     return parent as TreeViewItem; 
    } 
} 

LeftMarginMultiplierConverter

public class LeftMarginMultiplierConverter : IValueConverter 
{ 
    public double Length { get; set; } 

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     var item = value as TreeViewItem; 
     if (item == null) 
      return new Thickness(0); 

     return new Thickness(Length * item.GetDepth(), 0, 0, 0); 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     throw new System.NotImplementedException(); 
    } 
} 

kiểm soát

<TreeView Margin="50" HorizontalContentAlignment="Stretch"> 
    <TreeViewItem Header="test2"/> 
    <TreeViewItem Header="test2"> 
     <TreeViewItem Header="sub test"> 
      <TreeViewItem Header="sub test1-1"/> 
      <TreeViewItem Header="sub test1-2"/> 
     </TreeViewItem> 
     <TreeViewItem Header="sub test2"/> 
    </TreeViewItem> 
    <TreeViewItem Header="test3"/> 
</TreeView> 

Full TreeViewItem Phong cách

<SolidColorBrush x:Key="GlyphBrush" Color="#444" /> 

<!--================================================================= 
    TreeViewItem 
    ==================================================================--> 
<Style x:Key="ExpandCollapseToggleStyle" TargetType="ToggleButton"> 
    <Setter Property="Focusable" Value="False"/> 
    <Setter Property="Template"> 
    <Setter.Value> 
     <ControlTemplate TargetType="ToggleButton"> 
     <Grid 
      Width="15" 
      Height="13" 
      Background="Transparent"> 
      <Path x:Name="ExpandPath" 
      HorizontalAlignment="Left" 
      VerticalAlignment="Center" 
      Margin="1,1,1,1" 
      Fill="{StaticResource GlyphBrush}" 
      Data="M 4 0 L 8 4 L 4 8 Z"/> 
     </Grid> 
     <ControlTemplate.Triggers> 
      <Trigger Property="IsChecked" 
       Value="True"> 
      <Setter Property="Data" 
       TargetName="ExpandPath" 
       Value="M 0 4 L 8 4 L 4 8 Z"/> 
      </Trigger> 
     </ControlTemplate.Triggers> 
     </ControlTemplate> 
    </Setter.Value> 
    </Setter> 
</Style> 
<Style x:Key="TreeViewItemFocusVisual"> 
    <Setter Property="Control.Template"> 
    <Setter.Value> 
     <ControlTemplate> 
     <Border> 
      <Rectangle Margin="0,0,0,0" 
       StrokeThickness="5" 
       Stroke="Black" 
       StrokeDashArray="1 2" 
       Opacity="0"/> 
     </Border> 
     </ControlTemplate> 
    </Setter.Value> 
    </Setter> 
</Style> 


<Style x:Key="{x:Type TreeViewItem}" 
    TargetType="{x:Type TreeViewItem}"> 
    <Setter Property="Background" 
     Value="Transparent"/> 
    <Setter Property="HorizontalContentAlignment" 
     Value="{Binding Path=HorizontalContentAlignment, 
       RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/> 
    <Setter Property="VerticalContentAlignment" 
     Value="{Binding Path=VerticalContentAlignment, 
       RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/> 
    <Setter Property="Padding" 
     Value="1,0,0,0"/> 
    <Setter Property="Foreground" 
     Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/> 
    <Setter Property="FocusVisualStyle" 
     Value="{StaticResource TreeViewItemFocusVisual}"/> 
    <Setter Property="Template"> 
    <Setter.Value> 
     <ControlTemplate TargetType="{x:Type TreeViewItem}"> 
     <ControlTemplate.Resources> 
      <local:LeftMarginMultiplierConverter Length="19" x:Key="lengthConverter" /> 
     </ControlTemplate.Resources> 
     <StackPanel> 
     <Border Name="Bd" 
       Background="{TemplateBinding Background}" 
       BorderBrush="{TemplateBinding BorderBrush}" 
       BorderThickness="{TemplateBinding BorderThickness}" 
       Padding="{TemplateBinding Padding}"> 
      <Grid Margin="{Binding Converter={StaticResource lengthConverter}, 
           RelativeSource={RelativeSource TemplatedParent}}"> 
      <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> 
      <ItemsPresenter x:Name="ItemsHost" /> 
     </StackPanel> 
     <ControlTemplate.Triggers> 
      <Trigger Property="IsExpanded" 
       Value="false"> 
      <Setter TargetName="ItemsHost" 
       Property="Visibility" 
       Value="Collapsed"/> 
      </Trigger> 
      <Trigger Property="HasItems" 
       Value="false"> 
      <Setter TargetName="Expander" 
       Property="Visibility" 
       Value="Hidden"/> 
      </Trigger> 
      <MultiTrigger> 
      <MultiTrigger.Conditions> 
       <Condition Property="HasHeader" 
        Value="false"/> 
       <Condition Property="Width" 
        Value="Auto"/> 
      </MultiTrigger.Conditions> 
      <Setter TargetName="PART_Header" 
       Property="MinWidth" 
       Value="75"/> 
      </MultiTrigger> 
      <MultiTrigger> 
      <MultiTrigger.Conditions> 
       <Condition Property="HasHeader" 
        Value="false"/> 
       <Condition Property="Height" 
        Value="Auto"/> 
      </MultiTrigger.Conditions> 
      <Setter TargetName="PART_Header" 
       Property="MinHeight" 
       Value="19"/> 
      </MultiTrigger> 
      <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> 
     </ControlTemplate.Triggers> 
     </ControlTemplate> 
    </Setter.Value> 
    </Setter> 
</Style> 
+0

Vậy đó! Cảm ơn bạn rất nhiều cho tất cả các bài viết của bạn! – alex2k8

+0

Câu trả lời hay. +1 Cảm ơn rất nhiều. – Amenti

+0

Tuyệt vời! Tuy nhiên tôi đã nhận thấy một vấn đề mà độ sâu được tính toán không chính xác nếu chế độ xem dạng cây được tạo bằng cách sử dụng các mẫu phân cấp trong đó thuộc tính 'Parent' không được đặt trên' TreeViewItem'. Tôi đã chỉnh sửa câu trả lời để thay vì sử dụng cây trực quan để làm việc ra cha mẹ mà sửa chữa vấn đề (ít nhất là cho tôi), cảm thấy tự do để cuộn nó trở lại nếu bạn có bất kỳ phản đối mặc dù. – Justin

4

Nếu bạn có nghĩa là một cái gì đó giống như ảnh chụp màn hình này

LineItem Hightlighting in a TreeView http://www.bendewey.com/code/treeViewFullWidth.png

Sau đó, điều này sẽ giúp bạn. Dựa trên http://msdn.microsoft.com/en-us/library/ms788727.aspx bạn có thể thực hiện một số thay đổi đối với bố cục Lưới của TreeViewItem. Về cơ bản bạn loại bỏ cột thứ ba. Sau đó, trong TreeView bạn đặt HorizontalContentAlignment = "Stretch". Tôi đang gắn toàn bộ tài nguyên bên dưới, nhưng đây là phần quan trọng.

<!-- ... --> 
<ControlTemplate TargetType="{x:Type TreeViewItem}"> 
    <Grid> 
    <Grid.ColumnDefinitions> 
     <ColumnDefinition MinWidth="19" 
       Width="Auto"/> 
     <ColumnDefinition Width="*"/> 
    </Grid.ColumnDefinitions> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="Auto"/> 
     <RowDefinition/> 
    </Grid.RowDefinitions> 
    <!-- ... --> 

kiểm soát

<TreeView Margin="50" HorizontalContentAlignment="Stretch"> 
    <TreeViewItem Header="test2"/> 
    <TreeViewItem Header="test2"> 
     <TreeViewItem Header="sub test"/> 
     <TreeViewItem Header="sub test2"/> 
    </TreeViewItem> 
    <TreeViewItem Header="test3"/> 
</TreeView> 

Tài

<SolidColorBrush x:Key="GlyphBrush" Color="#444" /> 

<!--================================================================= 
    TreeViewItem 
==================================================================--> 
<Style x:Key="ExpandCollapseToggleStyle" TargetType="ToggleButton"> 
    <Setter Property="Focusable" Value="False"/> 
    <Setter Property="Template"> 
    <Setter.Value> 
     <ControlTemplate TargetType="ToggleButton"> 
     <Grid 
      Width="15" 
      Height="13" 
      Background="Transparent"> 
      <Path x:Name="ExpandPath" 
      HorizontalAlignment="Left" 
      VerticalAlignment="Center" 
      Margin="1,1,1,1" 
      Fill="{StaticResource GlyphBrush}" 
      Data="M 4 0 L 8 4 L 4 8 Z"/> 
     </Grid> 
     <ControlTemplate.Triggers> 
      <Trigger Property="IsChecked" 
       Value="True"> 
      <Setter Property="Data" 
       TargetName="ExpandPath" 
       Value="M 0 4 L 8 4 L 4 8 Z"/> 
      </Trigger> 
     </ControlTemplate.Triggers> 
     </ControlTemplate> 
    </Setter.Value> 
    </Setter> 
</Style> 
<Style x:Key="TreeViewItemFocusVisual"> 
    <Setter Property="Control.Template"> 
    <Setter.Value> 
     <ControlTemplate> 
     <Border> 
      <Rectangle Margin="0,0,0,0" 
       StrokeThickness="5" 
       Stroke="Black" 
       StrokeDashArray="1 2" 
       Opacity="0"/> 
     </Border> 
     </ControlTemplate> 
    </Setter.Value> 
    </Setter> 
</Style> 


<Style x:Key="{x:Type TreeViewItem}" 
    TargetType="{x:Type TreeViewItem}"> 
    <Setter Property="Background" 
     Value="Transparent"/> 
    <Setter Property="HorizontalContentAlignment" 
     Value="{Binding Path=HorizontalContentAlignment, 
       RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/> 
    <Setter Property="VerticalContentAlignment" 
     Value="{Binding Path=VerticalContentAlignment, 
       RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/> 
    <Setter Property="Padding" 
     Value="1,0,0,0"/> 
    <Setter Property="Foreground" 
     Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/> 
    <Setter Property="FocusVisualStyle" 
     Value="{StaticResource TreeViewItemFocusVisual}"/> 
    <Setter Property="Template"> 
    <Setter.Value> 
     <ControlTemplate TargetType="{x:Type TreeViewItem}"> 
     <Grid> 
      <Grid.ColumnDefinitions> 
      <ColumnDefinition MinWidth="19" 
         Width="Auto"/> 
      <ColumnDefinition Width="*"/> 
      </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}"> 
      <ContentPresenter x:Name="PART_Header" 
         ContentSource="Header" 
         HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"/> 
      </Border> 
      <ItemsPresenter x:Name="ItemsHost" 
        Grid.Row="1" 
        Grid.Column="1"/> 
     </Grid> 
     <ControlTemplate.Triggers> 
      <Trigger Property="IsExpanded" Value="false"> 
      <Setter TargetName="ItemsHost" Property="Visibility" Value="Collapsed"/> 
      </Trigger> 
      <Trigger Property="HasItems" Value="false"> 
      <Setter TargetName="Expander" Property="Visibility" Value="Hidden"/> 
      </Trigger> 
      <MultiTrigger> 
      <MultiTrigger.Conditions> 
       <Condition Property="HasHeader" Value="false"/> 
       <Condition Property="Width" Value="Auto"/> 
      </MultiTrigger.Conditions> 
      <Setter TargetName="PART_Header" Property="MinWidth" Value="75"/> 
      </MultiTrigger> 
      <MultiTrigger> 
      <MultiTrigger.Conditions> 
       <Condition Property="HasHeader" Value="false"/> 
       <Condition Property="Height" Value="Auto"/> 
      </MultiTrigger.Conditions> 
      <Setter TargetName="PART_Header" Property="MinHeight" Value="19"/> 
      </MultiTrigger> 
      <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> 
     </ControlTemplate.Triggers> 
     </ControlTemplate> 
    </Setter.Value> 
    </Setter> 
</Style> 
+0

Cảm ơn bạn, Bendewey. Nhưng giải pháp của bạn làm nổi bật dòng sau khi chuyển đổi. Tôi không thích nó để làm nổi bật toàn bộ dòng. Có vẻ lưới trong mẫu sẽ không cho phép điều này, bạn có biết bất kỳ giải pháp nào khác không? – alex2k8

+0

Chắc chắn là có thể. Tôi có thể viết lại điều gì đó cho bạn sau tối nay. nhưng về cơ bản bạn sẽ muốn thay đổi nó từ một lưới để có thể một stackpanel và sau đó đặt biểu tượng giãn nở bên trong biên giới. Bạn cũng sẽ phải thay đổi trình kích hoạt. – bendewey

+0

Điều đó thật tuyệt! Vì nó không phải là rõ ràng đối với tôi, làm thế nào chúng ta có thể thụt lề các nút mà không có C# nếu một số điều như StackPanel được sử dụng. – alex2k8

6

Nếu bạn có nghĩa là một cái gì đó giống như ảnh chụp màn hình này

Full Width TreeViewItem http://www.bendewey.com/code/treeViewFullWidth2.png

Cập nhật Như đã nói ở ví dụ này có sự sụp đổ của bị thụt vào subitems

Full Width TreeViewItem http://www.bendewey.com/code/treeViewFullWidth2a.png

Sau đó, điều này sẽ giúp bạn. Nó cũng dựa trên http://msdn.microsoft.com/en-us/library/ms788727.aspx bạn có thể thay đổi mẫu TreeViewItem thành một StackPanel và đặt ItemsPanel bên trái Margin thành 19. Sau đó, trong TreeView bạn đặt HorizontalContentAlignment = "Stretch". Tôi đang gắn toàn bộ tài nguyên bên dưới, nhưng đây là phần quan trọng.

<ControlTemplate TargetType="{x:Type TreeViewItem}"> 
<StackPanel> 
    <Border Name="Bd" 
     Background="{TemplateBinding Background}" 
     BorderBrush="{TemplateBinding BorderBrush}" 
     BorderThickness="{TemplateBinding BorderThickness}" 
     Padding="{TemplateBinding Padding}"> 
     <Grid> 
     <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> 
    <ItemsPresenter x:Name="ItemsHost" Margin="19,0,0,0" /> 
</StackPanel> 
<!-- Triggers --> 
</ControlTemplate> 

kiểm soát

<TreeView Margin="50" HorizontalContentAlignment="Stretch"> 
    <TreeViewItem Header="test2"/> 
    <TreeViewItem Header="test2"> 
     <TreeViewItem Header="sub test"/> 
     <TreeViewItem Header="sub test2"/> 
    </TreeViewItem> 
    <TreeViewItem Header="test3"/> 
</TreeView> 

Tài

<SolidColorBrush x:Key="GlyphBrush" Color="#444" /> 

<!--================================================================= 
     TreeViewItem 
    ==================================================================--> 
<Style x:Key="ExpandCollapseToggleStyle" TargetType="ToggleButton"> 
    <Setter Property="Focusable" Value="False"/> 
    <Setter Property="Template"> 
    <Setter.Value> 
     <ControlTemplate TargetType="ToggleButton"> 
     <Grid 
      Width="15" 
      Height="13" 
      Background="Transparent"> 
      <Path x:Name="ExpandPath" 
      HorizontalAlignment="Left" 
      VerticalAlignment="Center" 
      Margin="1,1,1,1" 
      Fill="{StaticResource GlyphBrush}" 
      Data="M 4 0 L 8 4 L 4 8 Z"/> 
     </Grid> 
     <ControlTemplate.Triggers> 
      <Trigger Property="IsChecked" 
       Value="True"> 
      <Setter Property="Data" 
       TargetName="ExpandPath" 
       Value="M 0 4 L 8 4 L 4 8 Z"/> 
      </Trigger> 
     </ControlTemplate.Triggers> 
     </ControlTemplate> 
    </Setter.Value> 
    </Setter> 
</Style> 
<Style x:Key="TreeViewItemFocusVisual"> 
    <Setter Property="Control.Template"> 
    <Setter.Value> 
     <ControlTemplate> 
     <Border> 
      <Rectangle Margin="0,0,0,0" 
       StrokeThickness="5" 
       Stroke="Black" 
       StrokeDashArray="1 2" 
       Opacity="0"/> 
     </Border> 
     </ControlTemplate> 
    </Setter.Value> 
    </Setter> 
</Style> 


<Style x:Key="{x:Type TreeViewItem}" 
    TargetType="{x:Type TreeViewItem}"> 
    <Setter Property="Background" 
     Value="Transparent"/> 
    <Setter Property="HorizontalContentAlignment" 
     Value="{Binding Path=HorizontalContentAlignment, 
       RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/> 
    <Setter Property="VerticalContentAlignment" 
     Value="{Binding Path=VerticalContentAlignment, 
       RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/> 
    <Setter Property="Padding" 
     Value="1,0,0,0"/> 
    <Setter Property="Foreground" 
     Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/> 
    <Setter Property="FocusVisualStyle" 
     Value="{StaticResource TreeViewItemFocusVisual}"/> 
    <Setter Property="Template"> 
    <Setter.Value> 
     <ControlTemplate TargetType="{x:Type TreeViewItem}"> 
     <StackPanel> 
      <Border Name="Bd" 
       Background="{TemplateBinding Background}" 
       BorderBrush="{TemplateBinding BorderBrush}" 
       BorderThickness="{TemplateBinding BorderThickness}" 
       Padding="{TemplateBinding Padding}"> 
      <Grid> 
       <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> 
      <ItemsPresenter x:Name="ItemsHost" Margin="19,0,0,0" /> 
     </StackPanel> 
     <ControlTemplate.Triggers> 
      <Trigger Property="IsExpanded" 
       Value="false"> 
      <Setter TargetName="ItemsHost" 
       Property="Visibility" 
       Value="Collapsed"/> 
      </Trigger> 
      <Trigger Property="HasItems" 
       Value="false"> 
      <Setter TargetName="Expander" 
       Property="Visibility" 
       Value="Hidden"/> 
      </Trigger> 
      <MultiTrigger> 
      <MultiTrigger.Conditions> 
       <Condition Property="HasHeader" 
        Value="false"/> 
       <Condition Property="Width" 
        Value="Auto"/> 
      </MultiTrigger.Conditions> 
      <Setter TargetName="PART_Header" 
       Property="MinWidth" 
       Value="75"/> 
      </MultiTrigger> 
      <MultiTrigger> 
      <MultiTrigger.Conditions> 
       <Condition Property="HasHeader" 
        Value="false"/> 
       <Condition Property="Height" 
        Value="Auto"/> 
      </MultiTrigger.Conditions> 
      <Setter TargetName="PART_Header" 
       Property="MinHeight" 
       Value="19"/> 
      </MultiTrigger> 
      <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> 
     </ControlTemplate.Triggers> 
     </ControlTemplate> 
    </Setter.Value> 
    </Setter> 
</Style> 
+0

Cảm ơn bạn! Nhưng nếu bạn đi đến các nút con, bạn sẽ thấy không gian màu trắng ở bên trái của nút chuyển đổi. Tôi muốn chọn dòng ĐẦY ĐỦ. Giải pháp giả là: ItemsPresenter.margin = "0", và ColumnDefinition Width = "19 * Level". Tôi đã cố gắng sử dụng MarkupExension để tính toán Cấp độ - không có may mắn. Bất kỳ ý tưởng? – alex2k8

1

Nguồn của vấn đề khi sử dụng TreeView với ItemsSource được, refered từ link text, tôi đã thay đổi một số mã của lớp TreeViewItemExtensions:

public static class TreeViewItemExtensions 
{ 
    public static int GetDepth(this TreeViewItem item) 
    { 
     while (GetSelectedTreeViewItemParent(item) != null) 
     { 
      var parent = GetSelectedTreeViewItemParent(item); 
      if (parent != null) 
       return parent.GetDepth() + 1; 

      item = parent; 
     } 
     return 0; 
} 

public static TreeViewItem GetSelectedTreeViewItemParent(this TreeViewItem item) 
{ 
     DependencyObject parent = VisualTreeHelper.GetParent(item); 
     while (!(parent is TreeViewItem || parent is TreeView)) 
     { 
      parent = VisualTreeHelper.GetParent(parent); 
     } 

     return parent as TreeViewItem; 
    } 
} 
3

này là do đến nay là giải pháp dễ nhất. Chỉ cần tạo một hình chữ nhật, gọi nó là Hb và đặt lề của nó thành -100px và không hiển thị. Chỉ đặt nó thành Hiển thị khi bạn đã chọn hoặc di chuột qua. Đó là một hack, nhưng bạn tốt cho lên đến 5 mức TreeViewItems lồng nhau (100> 19 * 5)

 <ControlTemplate TargetType="{x:Type TreeViewItem}"> 
    <Grid> 
    <Grid.ColumnDefinitions> 
    <ColumnDefinition MinWidth="19" Width="Auto"/> 
    <ColumnDefinition Width="*"/> 
    </Grid.ColumnDefinitions> 
    <Grid.RowDefinitions> 
    <RowDefinition Height="Auto"/> 
    <RowDefinition/> 
    </Grid.RowDefinitions> 
         <ToggleButton x:Name="Expander" Style="{StaticResource ExpandCollapseToggleStyle}" IsChecked="{Binding IsExpanded, RelativeSource={RelativeSource TemplatedParent}}" ClickMode="Press" VerticalAlignment="Top" Panel.ZIndex="1"/> 
    <Rectangle x:Name="Hb" Width="Auto" Height="Auto" Grid.ColumnSpan="2" Margin="-100,0,0,0" Panel.ZIndex="-1" Visibility="Hidden" /> 
         <Border x:Name="Bd" SnapsToDevicePixels="true" BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}" Grid.Column="1" Panel.ZIndex="0"> 
    <ContentPresenter x:Name="PART_Header" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" ContentSource="Header" HorizontalAlignment="Stretch"/> 
    </Border> 
    <ItemsPresenter x:Name="ItemsHost" Grid.Column="0" Grid.Row="1" Grid.ColumnSpan="2" Margin="19,0,0,0"/> 
    </Grid> 
1

sử dụng một cái gì đó giống như theseven7 để tạo điều kiện sử dụng mã bendewey với TreeViewItems templated ...

public static int GetDepth(this TreeViewItem item) 
    { 
     FrameworkElement elem = item; 
     var parent = VisualTreeHelper.GetParent(item); 
     var count = 0; 
     while (parent != null && !(parent is TreeView)) 
     { 
      var tvi = parent as TreeViewItem; 
      if (parent is TreeViewItem) 
       count++; 
      parent = VisualTreeHelper.GetParent(parent); 
     } 
     return count; 
    } 
0

Tôi đã quản lý điều này bằng cách sao chép ItemContainerStyle bằng cách sử dụng kết hợp, đặt tên cho lưới mà mục được đặt vào và sau đó đặt nền của lưới.

+0

Đánh dấu, bạn có thể cung cấp một ví dụ không? Điều đó sẽ cực kỳ hữu ích. Những câu trả lời khác trông quá phức tạp. – Thomas

15

Tiêu đề TreeViewItem sẽ không kéo dài?

Sự cố này xảy ra do mẫu mặc định của WPF cho TreeViewItem được thiết lập dưới dạng 3 cột theo 2 hàng Grid. Hàng đầu tiên dành cho "tiêu đề" (thực tế là Border) và hàng thứ hai là dành cho số ItemsPresenter. Hai hàng được hiển thị hoặc ẩn khi cần thiết, để hoàn thành việc mở rộng cây khi bạn nhấp vào hình tam giác nhỏ - chiếm không cột số Grid.

Cả hai hàng thực sự chỉ cần một cột bổ sung. Ví dụ, trong hàng thứ hai, chúng ta không có gì ở col-0, row-1, bởi vì phần trống đó sẽ được thụt vào khi IsExpanded là đúng. Nhưng bí ẩn bắt đầu khi chúng tôi lưu ý rằng ItemsPresenter, có trụ sở tại col-1, hàng-1, chỉ định Grid.ColumnSpan=2.

Thật không may ở hàng trên cùng, Border giữ tiêu đề được đặt thành Grid.Column=1 ... nhưng không có ColumnSpan. Vì col-2 của GridWidth=* điều này có nghĩa là tiêu đề/đường viền sẽ không kéo theo chiều ngang.

Nói cách khác, tôi có vẻ như thiết kế lưới 3 cột không có mục đích ngoại trừ đặc biệt để ngăn tiêu đề kéo dài.Theo như tôi có thể nói, một sắp xếp 2x2 đơn giản sẽ linh hoạt hơn [chỉnh sửa: xem chú thích # 2] và hỗ trợ hoặc kéo dài toàn bộ tiêu đề không bị kéo dài, thông qua các cơ chế liên kết WPF thông thường.

Lý tưởng nhất, chúng tôi muốn thay đổi Grid chỉ có 2 cột thay vì 3. Kể từ đó không phải là dễ dàng như vậy, thay vì chúng tôi sẽ làm cho khoảng tiêu đề 2 cột, giống như ItemsPresenter làm.

Ok, đây là một nhỏ, hoàn chỉnh, khép kín (XAML-only) chương trình mà chứng minh làm việc - và các bản sửa lỗi - các vấn đề:

<Window x:Class="WpfApplication1.MainWindow" 
    xmlns="http://schemas.microsoft.com/netfx/2007/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:r="clr-namespace:System.Reflection;assembly=mscorlib" 
    xmlns:sys="clr-namespace:System;assembly=mscorlib" 
    Width="800" SizeToContent="Manual"> 

    <TreeView ItemsSource="{Binding Source={StaticResource data}}" 
      VirtualizingStackPanel.VirtualizationMode="Recycling" 
      VirtualizingStackPanel.IsVirtualizing="True" 
      VirtualizingPanel.ScrollUnit="Item"> 

    <TreeView.Resources> 
     <ObjectDataProvider x:Key="data" ObjectInstance="{x:Static sys:AppDomain.CurrentDomain}" MethodName="GetAssemblies" /> 

     <HierarchicalDataTemplate DataType="{x:Type r:Assembly}" ItemsSource="{Binding Path=DefinedTypes}" > 
      <TextBlock Text="{Binding Path=Location}" /> 
     </HierarchicalDataTemplate> 
     <HierarchicalDataTemplate DataType="{x:Type sys:Type}" ItemsSource="{Binding Path=CustomAttributes}"> 
      <TextBlock Text="{Binding Path=Name}" /> 
     </HierarchicalDataTemplate> 
     <HierarchicalDataTemplate DataType="{x:Type r:CustomAttributeData}" ItemsSource="{Binding Path=ConstructorArguments}"> 
      <TextBlock Text="{Binding Path=AttributeType.Name}" /> 
     </HierarchicalDataTemplate> 
    </TreeView.Resources> 

    <TreeView.ItemContainerStyle> 
     <Style TargetType="{x:Type TreeViewItem}"> 

      <!-- == == BEGIN HERE == == --> 
      <Style.Resources> 
       <Style TargetType="{x:Type Border}"> 
        <Setter Property="Grid.ColumnSpan" Value="2" /> 
       </Style> 
      </Style.Resources> 
      <!-- == == == END == == == --> 

      <Setter Property="Background" Value="LightBlue" /> 

     </Style> 
    </TreeView.ItemContainerStyle> 
    </TreeView> 
</Window> 

Nếu bạn chạy chương trình này như thể hiện bạn sẽ thấy một cái gì đó như thế này. Đây là hành vi cố định, cho phép bạn lấy lại toàn quyền kiểm soát các hành vi kéo dài của TreeViewItem tiêu đề:

enter image description here

Thông báo BEGIN/END phần với đường chấm trong nguồn XAML. Về cơ bản, tôi chỉ đặt Grid.ColumnSpan=2 trên vi phạm Border, để nó sẽ lấp đầy chiều rộng kéo dài của Grid. Phần tử đó được phát ra bởi mẫu TreeViewItem, vì vậy tôi nhận thấy rằng một cách hiệu quả để thay đổi thuộc tính của nó là thông qua nhắm mục tiêu Style trong từ điển tài nguyên của TreeViewItem 's Style. Vâng, khó hiểu. Bạn có thể truy cập Style qua TreeViewItem.ItemContainerStyle.

Để xem (hiện có) hành vi bị hỏng, bạn có thể nhận xét ra phần giữa đường chấm:

enter image description here

Bạn cũng có thể thiết lập các phong cách trong một số từ điển tài nguyên, thay vì sử dụng ItemContainerStyle bất động sản như tôi đã làm ở đây. Tôi đã làm theo cách này bởi vì nó giảm thiểu phạm vi sửa chữa, do đó các điều khiển Border không liên quan sẽ không bị ảnh hưởng. Nếu bạn cần một cách phân biệt đối xử hơn để nhắm mục tiêu điều khiển này, bạn có thể tận dụng lợi thế của thực tế là nó có Name='Bd'.


[sửa:] Giải pháp này không không phản ánh sử dụng! Đừng sợ hãi bởi dữ liệu demo vô nghĩa - nó không liên quan gì đến vấn đề này; nó chỉ là cách dễ nhất để lấy một số dữ liệu phân cấp cho mục đích trình diễn, trong khi vẫn giữ toàn bộ chương trình nhỏ.


[sửa # 2:] Tôi chỉ nhận ra rằng những gì các nhà thiết kế đã cố gắng để tránh với sự sắp xếp lưới 3x2 là hiệu ứng khó coi sau (phóng đại ở đây bằng một ảnh chụp màn hình thu nhỏ).Vì vậy, nếu bạn áp dụng một trong những giải pháp từ trang này, được cảnh báo trước rằng bạn có thể không muốn điều này:

enter image description here

+1

Nếu bạn không cần lựa chọn để mở rộng sang lề trái, đây là một giải pháp gọn nhẹ. –

+0

câu trả lời tuyệt vời. bạn đã tiết kiệm thời gian của tôi. –

0

Đối với một chỉ XAML cách tiếp cận tôi đã thực hiện một giải pháp Bendewey và phá vỡ nó lên một chút vào một giải pháp cơ bản hơn:

phong cách dưới đây sẽ cho phép các mặt hàng TreeView để span:

<Style TargetType="{x:Type TreeViewItem}">   
    <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="{x:Type TreeViewItem}">      
       <Grid> 
        <Grid.ColumnDefinitions> 
         <ColumnDefinition MinWidth="19" 
        Width="Auto"/> 
         <ColumnDefinition Width="*"/> 
        </Grid.ColumnDefinitions> 
        <Grid.RowDefinitions> 
         <RowDefinition Height="Auto"/> 
         <RowDefinition/> 
        </Grid.RowDefinitions> 
        <ToggleButton x:Name="Expander" 
       Content="..." 
       IsChecked="{Binding Path=IsExpanded, 
          RelativeSource={RelativeSource TemplatedParent}}" 
       ClickMode="Press"/> 
        <Border Name="Bd" Grid.Column="1" Background="Red" Padding="3"> 
         <ContentPresenter x:Name="PART_Header" ContentSource="Header" 
        HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"/> 
        </Border> 
        <ItemsPresenter x:Name="ItemsHost" Grid.Row="1" Grid.Column="1"/> 
       </Grid> 
     <!-- ADD TRIGGERS HERE -->         
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 

để có được nó để hoạt động và sụp đổ như một Treeview thích những nguyên nhân dưới đây sẽ cho phép điều này:

<ControlTemplate.Triggers>           
        <MultiTrigger> 
         <MultiTrigger.Conditions> 
          <Condition Property="HasHeader" Value="false"/> 
          <Condition Property="Width" Value="Auto"/> 
         </MultiTrigger.Conditions>        
        </MultiTrigger> 
        <MultiTrigger> 
         <MultiTrigger.Conditions> 
          <Condition Property="HasHeader" Value="false"/> 
          <Condition Property="Height" Value="Auto"/> 
         </MultiTrigger.Conditions>       
        </MultiTrigger>       
        <MultiTrigger> 
         <MultiTrigger.Conditions> 
          <Condition Property="IsSelected" Value="true"/> 
          <Condition Property="IsSelectionActive" Value="false"/> 
         </MultiTrigger.Conditions>            
        </MultiTrigger> 
        <Trigger Property="IsSelected" Value="true"> 
         <Setter TargetName="Bd" Property="Background" Value="Blue"/>       
        </Trigger> 
        <Trigger Property="HasItems" Value="false"> 
         <Setter TargetName="Expander" Property="Visibility" Value="Hidden"/> 
        </Trigger> 
        <Trigger Property="IsExpanded" Value="false"> 
         <Setter TargetName="ItemsHost" 
           Property="Visibility" 
           Value="Collapsed"/> 
        </Trigger> 
</ControlTemplate.Triggers> 

Chỉ lồng các trình kích hoạt trong Mẫu điều khiển. Màu sắc/padding/thiết kế sẽ cần phải được tinh chỉnh cho phù hợp với nhu cầu của riêng bạn nhưng ở trên nên là một ý tưởng rất cơ bản về một nền tảng chỉ XAML.

Các vấn đề liên quan