When you like to design something like this in a Style, you'll need to modify the Template of TreeViewItem via Style.
The following shows the basic TreeViewItem-Style you will get when you want to change it using Expression Blend:
<Style x:Key="TreeViewItemFocusVisual">
<Setter Property="Control.Template">
<Setter.Value> <ControlTemplate> <Rectangle/> </ControlTemplate> </Setter.Value> </Setter> </Style>
<Setter Property="Control.Template">
<Setter.Value> <ControlTemplate> <Rectangle/> </ControlTemplate> </Setter.Value> </Setter> </Style>
<PathGeometry x:Key="TreeArrow" Figures="M0,0 L0,6 L6,0 z"/>
<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
Property="Stroke"
TargetName="ExpandPath" Value="#FF1BBBFA"/>
<Setter Property="Fill" TargetName="ExpandPath" Value="Transparent"/>
</Trigger>
<Trigger
Property="IsChecked" Value="True">
<Setter
Property="RenderTransform" TargetName="ExpandPath">
<Setter.Value>
<RotateTransform
Angle="180"
CenterX="3"
CenterY="3"/>
</Setter.Value>
</Setter>
<Setter
Property="Fill"
TargetName="ExpandPath" Value="#FF595959"/>
<Setter Property="Stroke" TargetName="ExpandPath" Value="#FF262626"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="StretchedTreeViewItemStyle" TargetType="{x:Type TreeViewItem}">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="HorizontalContentAlignment"
Value="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource
AncestorType={x:Type
ItemsControl}}}"/>
<Setter Property="VerticalContentAlignment"
Value="{Binding 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="Auto"/>
<ColumnDefinition
Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition
Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<ToggleButton
x:Name="Expander" Style="{StaticResource
ExpandCollapseToggleStyle}" ClickMode="Press" IsChecked="{Binding IsExpanded, RelativeSource={RelativeSource
TemplatedParent}}"/>
<Border
x:Name="Bd" SnapsToDevicePixels="true" Background="{TemplateBinding
Background}"
BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding
BorderThickness}"
Padding="{TemplateBinding Padding}" Grid.Column="1">
<ContentPresenter
x:Name="PART_Header" HorizontalAlignment="{TemplateBinding
HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding
SnapsToDevicePixels}"
ContentSource="Header"/>
</Border>
<ItemsPresenter
x:Name="ItemsHost" HorizontalAlignment="Stretch" Grid.Column="1" Grid.ColumnSpan="2" Grid.Row="1"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger
Property="IsExpanded" Value="false">
<Setter
Property="Visibility" TargetName="ItemsHost" Value="Collapsed"/>
</Trigger>
<Trigger Property="HasItems" Value="false">
<Setter
Property="Visibility" TargetName="Expander" Value="Hidden"/>
</Trigger>
<Trigger
Property="IsSelected" Value="true">
<Setter
Property="Background" TargetName="Bd" 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
Property="Background" TargetName="Bd" 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.Triggers>
<Trigger Property="VirtualizingStackPanel.IsVirtualizing" Value="true">
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<VirtualizingStackPanel HorizontalAlignment="Stretch"/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
The marked section shows us, how a basic TreeViewItem is designed:
We will change it to this layout:
The red section will look like this:
The Style then looks like this:
<Style x:Key="StretchedTreeViewItemWithLinesStyle" TargetType="{x:Type TreeViewItem}">
<Setter Property="AlternationCount" Value="{Binding
RelativeSource={RelativeSource Self}, Path=Items.Count}"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="HorizontalContentAlignment"
Value="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource
AncestorType={x:Type
ItemsControl}}}"/>
<Setter Property="VerticalContentAlignment"
Value="{Binding VerticalContentAlignment, RelativeSource={RelativeSource
AncestorType={x:Type
ItemsControl}}}"/>
<Setter Property="Padding" Value="0,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="15"
Width="Auto"/>
<ColumnDefinition
MinWidth="19"
Width="Auto"/>
<ColumnDefinition
Width="*"/>
<ColumnDefinition
Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition
Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid
Grid.Column="0"
Grid.ColumnSpan="2">
<Grid.RowDefinitions>
<RowDefinition
Height="*"/>
<RowDefinition
Height="Auto"/>
<RowDefinition
Height="*"/>
</Grid.RowDefinitions>
<Rectangle
Grid.Row="0"
Width="3"
Fill="Green"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="Stretch" HorizontalAlignment="Left"
Margin="5,0,0,0"/>
<Rectangle
Grid.Row="1"
Height="3"
Fill="Green"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" HorizontalAlignment="Left">
<Rectangle.Style>
<Style
TargetType="Rectangle">
<Setter
Property="Fill"
Value="{Binding RelativeSource={RelativeSource
AncestorType=ItemsControl},
Path=LinienFarbe}"/>
<Setter
Property="Margin"
Value="5,0,15,0"/>
<Setter Property="Width" Value="13"/>
<Style.Triggers>
<DataTrigger
Binding="{Binding RelativeSource={RelativeSource
AncestorType=ItemsControl},
Path=HasItems}"
Value="False">
<Setter
Property="Margin"
Value="5,0,0,0"></Setter>
<Setter
Property="Width"
Value="25"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Rectangle.Style>
</Rectangle>
</Grid>
<Border
Grid.Column="0"
Grid.ColumnSpan="2"
Grid.RowSpan="2">
<Rectangle
Grid.Row="2"
Width="3"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
VerticalAlignment="Stretch"
HorizontalAlignment="Left"
Margin="5,0,0,0"
Fill="Green">
<Rectangle.Style>
<Style
TargetType="Rectangle">
<Style.Triggers>
<DataTrigger
Value="True">
<DataTrigger.Binding>
<MultiBinding
Converter="{StaticResource MyAlternationEqualityConverter}">
<Binding
RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type ItemsControl}, AncestorLevel=2}" Path="Items.Count" />
<Binding
RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type TreeViewItem}}" Path="(ItemsControl.AlternationIndex)"
/>
</MultiBinding>
</DataTrigger.Binding>
<Setter
Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Rectangle.Style>
</Rectangle>
</Border>
<ToggleButton
Grid.Column="1"
x:Name="Expander" Style="{StaticResource
ExpandCollapseToggleStyle}" ClickMode="Press" IsChecked="{Binding IsExpanded, RelativeSource={RelativeSource
TemplatedParent}}"/>
<Border x:Name="Bd" SnapsToDevicePixels="true" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}" Grid.Column="2">
<ContentPresenter
x:Name="PART_Header" HorizontalAlignment="{TemplateBinding
HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding
SnapsToDevicePixels}"
ContentSource="Header"/>
</Border>
<ItemsPresenter
x:Name="ItemsHost" HorizontalAlignment="Stretch" Grid.Column="2" Grid.ColumnSpan="2" Grid.Row="1"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger
Property="IsExpanded" Value="false">
<Setter Property="Visibility" TargetName="ItemsHost" Value="Collapsed"/>
</Trigger>
<Trigger
Property="HasItems" Value="false">
<Setter
Property="Visibility" TargetName="Expander" Value="Hidden"/>
</Trigger>
<Trigger
Property="IsSelected" Value="true">
<Setter
Property="Background" TargetName="Bd" 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
Property="Background" TargetName="Bd" 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.Triggers>
<Trigger Property="VirtualizingStackPanel.IsVirtualizing" Value="true">
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<VirtualizingStackPanel HorizontalAlignment="Stretch"/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
The important parts are highlighted.
One note to the changes:
The last item has to know, that it is the last one. I found a solution based on this link: http://stackoverflow.com/questions/7834987/distinct-item-template-for-first-and-last-item-in-a-listview
By setting
AlternationCount
and implementing this
class MyAlternationEqualityConverter : IMultiValueConverter
{
#region
Implementation of IMultiValueConverter
public object Convert(object[]
values, Type targetType, object parameter, CultureInfo
culture)
{
if
(values != null && values.Length == 2
&&
values[0] is
int && values[1] is int)
{
bool
retval = Equals((int)values[0], (int)values[1] + 1);
return
retval;
}
return DependencyProperty.UnsetValue;
}
public object[] ConvertBack(object
value, Type[] targetTypes, object parameter, CultureInfo
culture)
{
throw new NotSupportedException();
}
#endregion
}
<DataTrigger Value="True"><DataTrigger.Binding>
<MultiBinding Converter="{StaticResource MyAlternationEqualityConverter}">
<Binding RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type ItemsControl}, AncestorLevel=2}" Path="Items.Count" />
<Binding RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type TreeViewItem}}" Path="(ItemsControl.AlternationIndex)" />
</MultiBinding>
</DataTrigger.Binding>
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
we can show or hide the down-going rectangle.
To get the sample shown on top this code does the work:
<Window x:Class="WpfApplication3.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication3"
Title="MainWindow" Height="200" Width="1900">
<Window.Resources>
<local:MyAlternationEqualityConverter
x:Key="MyAlternationEqualityConverter" />
<Style x:Key="TreeViewItemFocusVisual">
...
</Style>
<PathGeometry x:Key="TreeArrow" Figures="M0,0 L0,6 L6,0 z"/>
<Style x:Key="ExpandCollapseToggleStyle" TargetType="{x:Type ToggleButton}">
...
</Style>
<Style x:Key="StretchedTreeViewItemWithLinesStyle" TargetType="{x:Type TreeViewItem}">
...
</Style>
</Window.Resources>
<TreeView AlternationCount="{Binding
RelativeSource={RelativeSource Self}, Path=Items.Count}">
<TreeViewItem Header="Item2" Style="{StaticResource StretchedTreeViewItemWithLinesStyle}">
<TreeViewItem Header="SubItem1" Style="{StaticResource
StretchedTreeViewItemWithLinesStyle}"/>
<TreeViewItem Header="SubItem2" Style="{StaticResource
StretchedTreeViewItemWithLinesStyle}"/>
</TreeViewItem>
<TreeViewItem Header="Item3" Style="{StaticResource
StretchedTreeViewItemWithLinesStyle}"/>
</TreeView>
</Window>
And that's it :-)
Have fun,
Matthias
Properties for creating custom TreeView control
AntwortenLöschenIt's Great!!!
AntwortenLöschenCan you use this structure combine with grid or datagrid to treegrid?