前面一片文章实现TreeView的基本的模板重写,那么照着这个思路,我们再来写一个稍稍复杂的TreeView ,其它的内容都和前面系列内容相似,还是和之前文章介绍的一样,首先看看做出的DEMO的最终样式,先来一睹为快。
其实并不复杂,关键的是要准确去理解TreeView这个控件,这个控件的核心是TreeViewItem,那么我们就重点来看看这个样式该怎么写。
<Style TargetType="{x:Type TreeViewItem}"> <Setter Property="Background" Value="Transparent"/> <!--此处设置TreeViewItem的绑定样式--> <Setter Property="IsExpanded" Value="True"></Setter> <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="ItemsPanel"> <Setter.Value> <ItemsPanelTemplate> <StackPanel Orientation="Horizontal" IsItemsHost="True" Margin="10"></StackPanel> </ItemsPanelTemplate> </Setter.Value> </Setter> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type TreeViewItem}"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto" MinWidth="19"/> <ColumnDefinition Width="*"/> <ColumnDefinition Width="Auto"/> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="Auto" MinHeight="22"/> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="#00a3d9" Grid.Row="0" Grid.Column="1" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true" MaxWidth="300" HorizontalAlignment="Center" VerticalAlignment="Center"> <ContentPresenter x:Name="PART_Header" ContentSource="Header" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/> </Border> <Rectangle x:Name="VerLn" Grid.Row="1" Grid.Column="1" Width="1" Stroke="Green" HorizontalAlignment="Center" VerticalAlignment="Stretch" Height="50" SnapsToDevicePixels="true" Fill="White"/> <Border x:Name="itemsBorder" BorderBrush="#00a3d9" BorderThickness="1" Padding="2" Margin="10,0,10,0" Grid.ColumnSpan="3" Grid.Column="0" Grid.Row="2" HorizontalAlignment="Center" VerticalAlignment="Center"> <ItemsPresenter x:Name="ItemsHost" /> </Border> </Grid> <ControlTemplate.Triggers> <Trigger Property="IsExpanded" Value="false"> <Setter Property="Visibility" TargetName="ItemsHost" Value="Collapsed"/> </Trigger> <Trigger Property="HasItems" Value="false"> <Setter Property="Height" TargetName="VerLn" Value="0"/> <Setter Property="Height" TargetName="itemsBorder" Value="0"/> </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/> </ItemsPanelTemplate> </Setter.Value> </Setter> </Trigger> </Style.Triggers> </Style>
在这里我们把整个Grid分成了三行和三列,第0行第一列来来呈现我们每一个TreeViewItem的Header属性,我们让其居中显示,在第1行第一列我们来显示一条直线,这里我们也是用的Rectangle,当然使用Border和使用Path的效果其实是一样的,这个每个人习惯不同,最后面一行我们来显示ItemsPresenter,这个和上面一篇形式上是差不多的,我们就不详细介绍,这里需要重点注意的是下面的内容。
<Setter Property="ItemsPanel"> <Setter.Value> <ItemsPanelTemplate> <StackPanel Orientation="Horizontal" IsItemsHost="True" Margin="10"></StackPanel> </ItemsPanelTemplate> </Setter.Value> </Setter>
即ItemsPresenter是放在一个容器中的,这个容器决定了里面的Item到底需要通过怎样的方式来呈现,这里我们是使用的是横向排列的StackPanel控件来作为父容器的,另外需要注意到这个常用的Trigger
<Trigger Property="HasItems" Value="false"> <Setter Property="Height" TargetName="VerLn" Value="0"/> <Setter Property="Height" TargetName="itemsBorder" Value="0"/> </Trigger>
这个在TreeView控件中是非常常用的,这里需要特别注意。
接下里我们再看看当前的TreeView的具体数据绑定和其它的数据逻辑。
<TreeView Name="trvMenu" HorizontalContentAlignment="Center" VerticalContentAlignment="Center"> <TreeView.ItemTemplate> <HierarchicalDataTemplate DataType="{x:Type self:MyTreeViewItem}" ItemsSource="{Binding Children}"> <StackPanel Orientation="Horizontal" Margin="10"> <Ellipse x:Name="ellipse" Width="16" Height="16" Margin="2,0,2,0" Fill="Transparent"> <Ellipse.Triggers> <EventTrigger RoutedEvent="Loaded"> <BeginStoryboard> <Storyboard AutoReverse="True" RepeatBehavior="Forever"> <ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)" Storyboard.TargetName="ellipse"> <EasingColorKeyFrame KeyTime="0:0:0.0" Value="Transparent"/> <EasingColorKeyFrame KeyTime="0:0:0.5" Value="DarkGreen"/> </ColorAnimationUsingKeyFrames> </Storyboard> </BeginStoryboard> </EventTrigger> </Ellipse.Triggers> </Ellipse> <Image x:Name="image" Source="/TestTreeView;component/Images/connect.png" Margin="2,0,2,0" Width="24" Height="24" Stretch="Fill"> </Image> <TextBlock Text="{Binding TreeViewItemName}" VerticalAlignment="Center" FontSize="16" Foreground="White" Margin="2,0,2,0"/> </StackPanel> <HierarchicalDataTemplate.Triggers> <DataTrigger Binding="{Binding NodeType}" Value="采集服务器"> <Setter Property="Source" TargetName="image" Value="/TestTreeView;component/Images/connect.png"></Setter> </DataTrigger> <DataTrigger Binding="{Binding NodeType}" Value="控制服务器"> <Setter Property="Source" TargetName="image" Value="/TestTreeView;component/Images/medium_alarm_hit.png"></Setter> </DataTrigger> </HierarchicalDataTemplate.Triggers> </HierarchicalDataTemplate> </TreeView.ItemTemplate>
这里需要注意的是当前的TreeViewItem直接是作用在TreeView上的,如果TreeViewItem添加了x:Key属性,那么该如何引用该TreeViewItem样式呢?正确的方式是设置TreeView的ItemContainerStyle属性,这里需要注意,这篇文章就介绍到这里,如果能够与前面的一篇内容结合起来看,那么相信对TreeView控件会有更多的理解吧!