FluentTreeView Part.3

  1. 1. 自定义TreeView样式

上一篇中我们用数据驱动界面的方式使用了TreeView。这一篇我们稍稍改一改TreeView的样式。把TreeView表示节点可以展开的小三角替换成Expander是个不错的开始。既能复习TreeView的可视化树,又避免步子太大扯到蛋。

自定义TreeView样式

回顾一下,TreeView中我们所看到的所有Item,都是TreeViewItem负责呈现的。因此,我们需要重现实现TreeViewItem的Template。TreeViewItem要负责展示Item的内容,所以Template里应该要有一个ContentPreserenter;TreeViewItem自身也是个ItemsControl,Template里也应有一个ItemsPreserenter。除此之外就是表示Item是否可以展开的小三角,即我们要换成Expander的部分。
tree view with mark

结合图片分析一下TreeViewItem的可视化树。首先应有两行,第一行显示当前Item,第二行显示下一级Item;
其次应有两列,第一列放置小三角,第二列展示内容。应该是这样的结构:
|-|Column1|Column2|
|———-|———-|———-|
|Row1|Expander|ContentPreserenter|
|Row2|/|ItemsPreserenter|

跟其他控件不一样的是,在设计TreeViewItem的模板时,要先不管ItemsPreserenter那部分,就像它已经做好了一样。待到把其余部分的结构都定下来了,ItemsPreserenter部分自然就如愿了。这有实际上就是递归:ItemsPreserenter里有TreeViewItem的模板需要展开,这跟当前所做的问题,即重新实现TreeViewItem的模板,是一样的。我们在ItemsPreserenter的问题已经解决的假设上,解决了TreeViewItem的模板。这像极了汉诺塔。

习惯了这样的递归思考后,把几个显示隐藏的小细节处理好,这就得到了下面的XAML:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<Style TargetType="TreeViewItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TreeViewItem">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="24"></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<Expander IsExpanded="{Binding RelativeSource={RelativeSource TemplatedParent},Path=IsExpanded,Mode=TwoWay}" x:Name="expander"></Expander>
<ContentPresenter VerticalAlignment="Center" Grid.Column="1" ContentSource="Header"></ContentPresenter>
<ItemsPresenter Visibility="{Binding RelativeSource={RelativeSource TemplatedParent},Path=IsExpanded,Converter={StaticResource BoolToVisibilityConverter}}" Grid.Row="1" Grid.Column="1"></ItemsPresenter>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="HasItems" Value="False">
<Setter TargetName="expander" Property="Visibility" Value="Collapsed"></Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

expander-tree-view

大功告成!


源代码参见
https://github.com/Verrickt/Melchior-Sample/tree/master/FluentTreeView_Part3