Custom TreeView template to display hiearchical data in "a flow"
I have data structured in a hierarchical manner, that when being rendered with the TreeView control gets the output as below to the left. But I want to have the visual appearance looking more like the graph 开发者_运维百科on the right (mockup).
I've tried templating the TreeView and TreeViewItem controls but can't really get anything to work as I would've hoped. Any ideas?
this can be done in styles.
I have created one and hopefully you can start from here to achieve what you wanted. :)
<UserControl.Resources>
<ControlTemplate x:Key="CommonValidationToolTipTemplate" TargetType="ToolTip">
<Grid x:Name="Root" Margin="5,0" Opacity="0" RenderTransformOrigin="0,0">
<Grid.RenderTransform>
<TranslateTransform x:Name="Translation" X="-25"/>
</Grid.RenderTransform>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="OpenStates">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0"/>
<VisualTransition GeneratedDuration="0:0:0.2" To="Open">
<Storyboard>
<DoubleAnimation Duration="0:0:0.2" To="0" Storyboard.TargetProperty="X" Storyboard.TargetName="Translation">
<DoubleAnimation.EasingFunction>
<BackEase Amplitude=".3" EasingMode="EaseOut"/>
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
<DoubleAnimation Duration="0:0:0.2" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="Root"/>
</Storyboard>
</VisualTransition>
</VisualStateGroup.Transitions>
<VisualState x:Name="Closed">
<Storyboard>
<DoubleAnimation Duration="0" To="0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="Root"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Open">
<Storyboard>
<DoubleAnimation Duration="0" To="0" Storyboard.TargetProperty="X" Storyboard.TargetName="Translation"/>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="Root"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border Background="#052A2E31" CornerRadius="5" Margin="4,4,-4,-4"/>
<Border Background="#152A2E31" CornerRadius="4" Margin="3,3,-3,-3"/>
<Border Background="#252A2E31" CornerRadius="3" Margin="2,2,-2,-2"/>
<Border Background="#352A2E31" CornerRadius="2" Margin="1,1,-1,-1"/>
<Border Background="#FFDC000C" CornerRadius="2">
<TextBlock Foreground="White" MaxWidth="250" Margin="8,4,8,4" TextWrapping="Wrap" Text="{Binding (Validation.Errors)[0].ErrorContent}" UseLayoutRounding="false"/>
</Border>
</Grid>
</ControlTemplate>
<Style TargetType="sdk:TreeViewItem">
<Setter Property="Padding" Value="3"/>
<Setter Property="HorizontalContentAlignment" Value="Left"/>
<Setter Property="VerticalContentAlignment" Value="Top"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Cursor" Value="Arrow"/>
<Setter Property="IsTabStop" Value="True"/>
<Setter Property="TabNavigation" Value="Once"/>
<Setter Property="Margin" Value="0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="sdk:TreeViewItem">
<Border BorderThickness="1" BorderBrush="#FFB8E2B7" Margin="2,-1,2,2">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver"/>
<VisualState x:Name="Pressed"/>
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetProperty="Foreground" Storyboard.TargetName="Header">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<SolidColorBrush Color="#FF999999"/>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="SelectionStates">
<VisualState x:Name="Unselected"/>
<VisualState x:Name="Selected">
<Storyboard>
<DoubleAnimation Duration="0" To=".75" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="Selection"/>
</Storyboard>
</VisualState>
<VisualState x:Name="SelectedInactive">
<Storyboard>
<DoubleAnimation Duration="0" To=".2" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="Selection"/>
<ColorAnimation Duration="0" To="#FF999999" Storyboard.TargetProperty="Color" Storyboard.TargetName="SelectionFill"/>
<ColorAnimation Duration="0" To="#FF333333" Storyboard.TargetProperty="Color" Storyboard.TargetName="SelectionStroke"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="HasItemsStates">
<VisualState x:Name="HasItems"/>
<VisualState x:Name="NoItems">
<Storyboard>
<ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetProperty="Visibility" Storyboard.TargetName="ExpanderButton">
<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="ExpansionStates">
<VisualState x:Name="Collapsed"/>
<VisualState x:Name="Expanded">
<Storyboard>
<ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetProperty="Visibility" Storyboard.TargetName="ItemsHost">
<DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="ValidationStates">
<VisualState x:Name="Valid"/>
<VisualState x:Name="InvalidUnfocused">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="Validation">
<DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="InvalidFocused">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="Validation">
<DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="IsOpen" Storyboard.TargetName="ValidationToolTip">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<System:Boolean>True</System:Boolean>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid Background="{x:Null}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="15"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<ToggleButton x:Name="ExpanderButton" HorizontalAlignment="Stretch" IsTabStop="False" TabNavigation="Once" VerticalAlignment="Stretch">
<ToggleButton.Template>
<ControlTemplate TargetType="ToggleButton">
<Grid x:Name="Root" Background="Transparent">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimation Duration="0" To="#FF1BBBFA" Storyboard.TargetProperty="(Path.Stroke).Color" Storyboard.TargetName="UncheckedVisual"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<DoubleAnimation Duration="0" To=".7" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="Root"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="CheckStates">
<VisualState x:Name="Unchecked"/>
<VisualState x:Name="Checked">
<Storyboard>
<DoubleAnimation Duration="0" To="0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="UncheckedVisual"/>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="CheckedVisual"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Indeterminate"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid Margin="2">
<Rectangle x:Name="CheckedVisual" Fill="#FFFFFFFF" Stroke="#FF989898" StrokeThickness="1" StrokeLineJoin="Miter" RenderTransformOrigin="0.5,0.5" Margin="0,5" Width="11" Height="1" Opacity="0"/>
<Path x:Name="UncheckedVisual" Data="M4.9999995,6 L5.9999995,6 L5.9999995,10.5 L4.9999995,10.5 z M5.9999995,5 L10.5,5 L10.5,6 L5.9999995,6 z M0.5,5 L4.9999995,5 L4.9999995,6 L0.5,6 z M4.9999995,0.5 L5.9999995,0.5 L5.9999995,5 L4.9999995,5 z" Fill="#FFFFFFFF" Stretch="Fill" Stroke="#FF989898" StrokeThickness="1" StrokeLineJoin="Miter" UseLayoutRounding="False" Width="11" Height="11"/>
</Grid>
</Grid>
</ControlTemplate>
</ToggleButton.Template>
</ToggleButton>
<Rectangle x:Name="Selection" Grid.Column="1" IsHitTestVisible="False" Opacity="0" RadiusY="2" RadiusX="2" StrokeThickness="1">
<Rectangle.Fill>
<SolidColorBrush x:Name="SelectionFill" Color="#FFBADDE9"/>
</Rectangle.Fill>
<Rectangle.Stroke>
<SolidColorBrush x:Name="SelectionStroke" Color="#FF6DBDD1"/>
</Rectangle.Stroke>
</Rectangle>
<Button x:Name="Header" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Cursor="{TemplateBinding Cursor}" ClickMode="Hover" Grid.Column="1" Foreground="{TemplateBinding Foreground}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" IsTabStop="False" TabNavigation="Once" VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
<Button.Template>
<ControlTemplate TargetType="Button">
<Grid Background="{TemplateBinding Background}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="Pressed">
<Storyboard>
<DoubleAnimation Duration="0" To=".5" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="Hover"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<DoubleAnimation Duration="0" To=".55" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="Content"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Rectangle x:Name="Hover" Fill="#FFBADDE9" IsHitTestVisible="False" Opacity="0" RadiusY="2" RadiusX="2" Stroke="#FF6DBDD1" StrokeThickness="1"/>
<ContentPresenter x:Name="Content" Cursor="{TemplateBinding Cursor}" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" HorizontalAlignment="Left" Margin="{TemplateBinding Padding}"/>
</Grid>
</ControlTemplate>
</Button.Template>
<ContentPresenter ContentTemplate="{TemplateBinding HeaderTemplate}" Content="{TemplateBinding Header}"/>
</Button>
<Border x:Name="Validation" BorderBrush="#FFDB000C" BorderThickness="{TemplateBinding BorderThickness}" Grid.Column="1" CornerRadius="2" Visibility="Collapsed">
<ToolTipService.ToolTip>
<ToolTip x:Name="ValidationToolTip" DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}" IsHitTestVisible="True" Placement="Right" PlacementTarget="{Binding ElementName=Header}" Template="{StaticResource CommonValidationToolTipTemplate}"/>
</ToolTipService.ToolTip>
<Grid Background="Transparent" HorizontalAlignment="Right" Height="10" Margin="0,-4,-4,0" VerticalAlignment="Top" Width="10">
<Path Data="M 1,0 L6,0 A 2,2 90 0 1 8,2 L8,7 Z" Fill="#FFDC000C" Margin="-1,3,0,0"/>
<Path Data="M 0,0 L2,0 L 8,6 L8,8" Fill="#FFFFFFFF" Margin="-1,3,0,0"/>
</Grid>
</Border>
<ItemsPresenter x:Name="ItemsHost" Grid.Column="2" Grid.RowSpan="2" Visibility="Collapsed"/>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="White">
<sdk:TreeView>
<sdk:TreeViewItem Header="TreeViewItem" IsExpanded="True">
<sdk:TreeViewItem Header="TreeViewItem" IsExpanded="True">
<sdk:TreeViewItem Header="TreeViewItem" IsExpanded="True">
<sdk:TreeViewItem Header="TreeViewItem"/>
<sdk:TreeViewItem Header="TreeViewItem"/>
</sdk:TreeViewItem>
<sdk:TreeViewItem Header="TreeViewItem" Margin="0"/>
</sdk:TreeViewItem>
<sdk:TreeViewItem Header="TreeViewItem" Margin="0"/>
</sdk:TreeViewItem>
</sdk:TreeView>
</Grid>
精彩评论