FluentTreeView Part.3

上一篇中我们用数据驱动界面的方式使用了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

Licensed under CC BY-NC-SA 4.0
使用 Hugo 构建
主题 StackJimmy 设计