WPF自定义虚线树形控件

本文详细描述了一位开发者如何在WPF中为项目定制一个带虚线效果的树形控件,通过修改现有Tree控件样式,实现垂直虚线跨多节点并根据节点位置动态调整,分享了关键代码和转换器的使用方法。
摘要由CSDN通过智能技术生成

WPF自定义虚线树形控件

项目领导要求来一个带虚线的树形控件,说这个东西好看,但WPF没有这种虚线型树控件。首先想到是从网上找个现成的,但在网上查了半于,都不如意,没办法,自己写,开干。

项目中有Tree控件Style,直接从上面入手改动,关键在于垂直虚线如何跨多个子结点,而且在最后一个结点处,不能划满格竖线。

经过几轮反复,完成成品样式如下:

主要代码如下:

<Grid x:Name="gridRoot">

                        <Grid.ColumnDefinitions>

                            <ColumnDefinition Width="Auto"/>

                            <ColumnDefinition Width="Auto"/>

                            <ColumnDefinition Width="*"/>

                        </Grid.ColumnDefinitions>

                        <Grid.RowDefinitions>

                            <RowDefinition Height="Auto"/>

                            <RowDefinition Height="*"/>

                        </Grid.RowDefinitions>

                        <!---画竖线-->

                        <Grid>

                            <Grid.RowDefinitions>

                                <RowDefinition Height="*"/>

                                <RowDefinition Height="*"/>

                            </Grid.RowDefinitions>

                            <Rectangle x:Name="VerLn1" Width="1" Stroke="#8888" Margin="10,0,0,0"

                                 SnapsToDevicePixels="true" StrokeDashArray="2" StrokeThickness="1" />

                        </Grid>

                        <Grid Grid.Row="1">

                            <Rectangle x:Name="VerLn2" Width="1" Stroke="#8888" Margin="10,0,0,0"

                                 SnapsToDevicePixels="true" StrokeDashArray="2" StrokeThickness="1" />

                        </Grid>

                        <!---展开按钮-->

                        <Grid Grid.Column="1">

                            <Grid.ColumnDefinitions>

                                <ColumnDefinition Width="16"/>

                                <ColumnDefinition Width="Auto"/>

                            </Grid.ColumnDefinitions>

                            <Rectangle x:Name="HorLn" Height="1" Stroke="#8888"  Margin="0,0,0,0"      

                                 SnapsToDevicePixels="true" StrokeDashArray="2" StrokeThickness="1"

                                      />

                            <ToggleButton x:Name="Expander"  ClickMode="Press"  Margin="0,0,0,0" Grid.Column="1"

                                      IsChecked="{Binding IsExpanded, RelativeSource={RelativeSource TemplatedParent}}" >

                                <ToggleButton.Style>

                                    <Style 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 Background="Transparent" Height="16" Padding="5" Width="16">

                                                        <Path x:Name="ExpandPath" Data="M0,0 L0,6 L6,0 z" Fill="White" Stroke="#FF818181">

                                                            <Path.RenderTransform>

                                                                <RotateTransform Angle="135" CenterY="3" CenterX="3"/>

                                                            </Path.RenderTransform>

                                                        </Path>

                                                    </Border>

                                                    <ControlTemplate.Triggers>

                                                        <Trigger Property="IsChecked" Value="True">

                                                            <Setter Property="RenderTransform" TargetName="ExpandPath">

                                                                <Setter.Value>

                                                                    <RotateTransform Angle="180" CenterY="3" CenterX="3"/>

                                                                </Setter.Value>

                                                            </Setter>

                                                            <Setter Property="Fill" TargetName="ExpandPath" Value="#FF595959"/>

                                                            <Setter Property="Stroke" TargetName="ExpandPath" Value="#FF262626"/>

                                                        </Trigger>

                                                        <Trigger Property="IsMouseOver" Value="True">

                                                            <Setter Property="Stroke" TargetName="ExpandPath" Value="#FF27C7F7"/>

                                                            <Setter Property="Fill" TargetName="ExpandPath" Value="#FFCCEEFB"/>

                                                        </Trigger>

                                                        <MultiTrigger>

                                                            <MultiTrigger.Conditions>

                                                                <Condition Property="IsMouseOver" Value="True"/>

                                                                <Condition Property="IsChecked" Value="True"/>

                                                            </MultiTrigger.Conditions>

                                                            <Setter Property="Stroke" TargetName="ExpandPath" Value="#FF1CC4F7"/>

                                                            <Setter Property="Fill" TargetName="ExpandPath" Value="#FF82DFFB"/>

                                                        </MultiTrigger>

                                                    </ControlTemplate.Triggers>

                                                </ControlTemplate>

                                            </Setter.Value>

                                        </Setter>

                                    </Style>

                                </ToggleButton.Style>

                            </ToggleButton>

                        </Grid>

                        <!---标题-->

                        <Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Grid.Column="2" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="True">

                            <!---此处HorizontalAlignment="Strech",则为扩充。HorizontalContentAlignment默认=LEFT-->

                            <ContentPresenter x:Name="PART_Header" ContentTemplate="{TemplateBinding HeaderTemplate}" Content="{TemplateBinding Header}"

                                              ContentStringFormat="{TemplateBinding HeaderStringFormat}" ContentSource="Header" HorizontalAlignment="{TemplateBinding HorizontalAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>

                        </Border>

                        <Grid  Grid.Column="2" Grid.Row="1" Margin="20,0,0,0" >

                            <ItemsPresenter x:Name="ItemsHost"  />

                        </Grid>

                    </Grid>

其中,灰底处代码分别为垂直虚线与横虚线。垂直虚线有两条,分别为:VerLn1、VerLn2,VerLn1用于指向自身结点,VerLn2用于包容子结点项。VerLn1采用RowSpan跨两行,当结点为本层最后一个结点时,VerLn1只跨一行,通过触发器来控制,代码如下:

  <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Converter={StaticResource LineConverter}}" Value="True">

                            <Setter TargetName="VerLn1" Property="Grid.RowSpan" Value="1"/>

                            <Setter Property="Visibility" TargetName="VerLn2" Value="Collapsed"/>

                        </DataTrigger>

                        <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Converter={StaticResource LineConverter}}" Value="False">

                            <Setter TargetName="VerLn1" Property="Grid.RowSpan" Value="2"/>

                        </DataTrigger>

代码中LineConverter为转换器,用于判断是否为本层最后一个结点。代码如下:

public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)

        {

            TreeViewItem item = (TreeViewItem)value;

            ItemsControl ctl = ItemsControl.ItemsControlFromItemContainer(item);

            bool bOk = ctl.ItemContainerGenerator.IndexFromContainer(item) == ctl.Items.Count - 1;

            return bOk;

        }

自定义的树形控件完成,前端可通过拼装列表,构建树型列表。

原码下载:https://download.csdn.net/download/ACODE1/89050468

  • 25
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值