自定义TreeView样式

自定义TreeView样式结果,实现类似VS的资源管理器折叠菜单效果

效果

在这里插入图片描述
注意:文件夹图标根据折叠情况变换,上图展示的图标使用了Icon也可以使用Image控制

关于Icon资源可以翻看前面的文章有介绍使用

思路

1:重定义TreeView的数据模板(HierarchicalDataTemplate) —— 能够帮助层级控件显示层级数据的模板是HierarchicalDataTemplate
2:重定义TreeViewItem的样式模板,绑定对应的数据内容(可根据自身数据需求处理)
3:模板中定义事件监控折叠开关,通过事件调整不同展示状态下的效果功能

xaml

<UserControl x:Class="Wpf.AvalonDock.UserControls.TestTreeView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:BbFrame="clr-namespace:Wpf.AvalonDock.UserControls"
             xmlns:local="clr-namespace:Wpf.AvalonDock.UserControls"
             mc:Ignorable="d" x:Name="My_TV">
    <UserControl.Resources>
        <Style x:Key="TreeViewItemFocusVisual">
            <Setter Property="Control.Template">
                <Setter.Value>
                    <ControlTemplate>
                        <Rectangle/>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
        <SolidColorBrush x:Key="TreeViewItem.TreeArrow.Static.Checked.Fill" Color="#FF595959"/>
        <SolidColorBrush x:Key="TreeViewItem.TreeArrow.Static.Checked.Stroke" Color="#FF262626"/>
        <SolidColorBrush x:Key="TreeViewItem.TreeArrow.MouseOver.Stroke" Color="#FF27C7F7"/>
        <SolidColorBrush x:Key="TreeViewItem.TreeArrow.MouseOver.Fill" Color="#FFCCEEFB"/>
        <SolidColorBrush x:Key="TreeViewItem.TreeArrow.MouseOver.Checked.Stroke" Color="#FF1CC4F7"/>
        <SolidColorBrush x:Key="TreeViewItem.TreeArrow.MouseOver.Checked.Fill" Color="#FF82DFFB"/>
        <PathGeometry x:Key="TreeArrow" Figures="M0,0 L0,6 L6,0 z"/>
        <SolidColorBrush x:Key="TreeViewItem.TreeArrow.Static.Fill" Color="#FFFFFFFF"/>
        <SolidColorBrush x:Key="TreeViewItem.TreeArrow.Static.Stroke" Color="#FF818181"/>
        <SolidColorBrush x:Key="TreeViewItemCheck_True" Color="#FF27C7F7" Opacity="0.3"/>
        <Style x:Key="ExpandCollapseToggleStyle" 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,5,5,5" Width="16">
                            <Path x:Name="ExpandPath" Data="{StaticResource TreeArrow}" Fill="{StaticResource TreeViewItem.TreeArrow.Static.Fill}" Stroke="{StaticResource TreeViewItem.TreeArrow.Static.Stroke}">
                                <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="{StaticResource TreeViewItem.TreeArrow.Static.Checked.Fill}"/>
                                <Setter Property="Stroke" TargetName="ExpandPath" Value="{StaticResource TreeViewItem.TreeArrow.Static.Checked.Stroke}"/>
                            </Trigger>
                            <Trigger Property="IsMouseOver" Value="True">
                                <Setter Property="Stroke" TargetName="ExpandPath" Value="{StaticResource TreeViewItem.TreeArrow.MouseOver.Stroke}"/>
                                <Setter Property="Fill" TargetName="ExpandPath" Value="{StaticResource TreeViewItem.TreeArrow.MouseOver.Fill}"/>
                            </Trigger>
                            <MultiTrigger>
                                <MultiTrigger.Conditions>
                                    <Condition Property="IsMouseOver" Value="True"/>
                                    <Condition Property="IsChecked" Value="True"/>
                                </MultiTrigger.Conditions>
                                <Setter Property="Stroke" TargetName="ExpandPath" Value="{StaticResource TreeViewItem.TreeArrow.MouseOver.Checked.Stroke}"/>
                                <Setter Property="Fill" TargetName="ExpandPath" Value="{StaticResource TreeViewItem.TreeArrow.MouseOver.Checked.Fill}"/>
                            </MultiTrigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
        <Style TargetType="{x:Type TreeViewItem}">
            <Setter Property="Background" Value="Transparent"/>
            <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="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type TreeViewItem}">
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition MinWidth="19" Width="Auto"/>
                                <ColumnDefinition Width="*"/>
                            </Grid.ColumnDefinitions>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="Auto"/>
                                <RowDefinition/>
                            </Grid.RowDefinitions>
                            <ToggleButton x:Name="Expander" ClickMode="Press" PreviewMouseDown="ProductListItem_DoubleClick" IsChecked="{Binding IsExpanded, RelativeSource={RelativeSource TemplatedParent}}" Style="{StaticResource ExpandCollapseToggleStyle}"/>
                            <Border x:Name="Bd" Grid.Column="1" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true">
                                <!--<ContentPresenter x:Name="PART_Header" ContentSource="Header" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>-->
                                <StackPanel x:Name="CBbPropertyNodeName" Tag="{Binding CBbFrameType}" Width="{Binding ElementName=My_TV, Path=Width}"
                                            HorizontalAlignment="Left" VerticalAlignment="Center" 
                                            Orientation="Horizontal" ContextMenu="{Binding m_contextMenu}">
                                    <!--<Image VerticalAlignment="Center" Source="{Binding Image, Mode=TwoWay}" Width="16" Height="16"/>-->
                                    <TextBlock x:Name="My_Icon" FontSize="18" Foreground="#558CDD" 
                                               Text="{Binding Icon, Mode=TwoWay}" Margin="2"
                                               FontFamily="pack://application:,,,/Wpf.AvalonDock;component/Font/#icomoon"/>
                                    <TextBlock x:Name="CBbPropertyNodeTName" VerticalAlignment="Center" HorizontalAlignment="Center"
                                               Height="25" Padding="5"
                                               Text="{Binding m_strName, Mode=TwoWay, UpdateSourceTrigger=LostFocus}"/>
                                </StackPanel>
                            </Border>
                            <ItemsPresenter x:Name="ItemsHost" Grid.Row="1" Grid.Column="1"/>
                        </Grid>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsExpanded" Value="false">
                                <Setter Property="Visibility" TargetName="ItemsHost" Value="Collapsed"/>
                            </Trigger>
                            <Trigger Property="HasItems" Value="false">
                                <Setter Property="Visibility" TargetName="Expander" Value="Hidden"/>
                            </Trigger>
                            <Trigger Property="IsSelected" Value="true">
                                <Setter Property="Background" TargetName="Bd" Value="{DynamicResource TreeViewItemCheck_True}"/>
                                <Setter Property="Foreground" Value="Black"/>
                            </Trigger>
                            <MultiTrigger>
                                <MultiTrigger.Conditions>
                                    <Condition Property="IsSelected" Value="true"/>
                                    <Condition Property="IsSelectionActive" Value="false"/>
                                </MultiTrigger.Conditions>
                                <Setter Property="Background" TargetName="Bd" Value="Transparent"/>
                                <Setter Property="Foreground" Value="Black"/>
                            </MultiTrigger>
                            <Trigger Property="IsEnabled" Value="false">
                                <Setter Property="Foreground" Value="Gray"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            <EventSetter Event="MouseDoubleClick" Handler="ProductListItem_DoubleClick"/>
            <!--<Style.Triggers>
                <Trigger Property="VirtualizingPanel.IsVirtualizing" Value="true">
                    <Setter Property="ItemsPanel">
                        <Setter.Value>
                            <ItemsPanelTemplate>
                                <VirtualizingStackPanel/>
                            </ItemsPanelTemplate>
                        </Setter.Value>
                    </Setter>
                </Trigger>
            </Style.Triggers>-->
        </Style>
    </UserControl.Resources>
    <TreeView Name="TView" BorderThickness="0">
        <TreeView.ItemTemplate>
            <HierarchicalDataTemplate DataType="{x:Type BbFrame:CBbPropertyNodeItem}" ItemsSource="{Binding Path=Children}">
                <!--<StackPanel x:Name="CBbPropertyNodeName" Tag="{Binding CBbFrameType}" Width="{Binding ElementName=My_TV, Path=Width}"
                            HorizontalAlignment="Center" VerticalAlignment="Center" Background="Red"
                            PreviewMouseLeftButtonDown="CBbPropertyNodeName_PreviewMouseLeftButtonDown"
                            Orientation="Horizontal" ContextMenu="{Binding m_contextMenu}">
                    <Image VerticalAlignment="Center" Source="{Binding Icon}" Width="16" Height="16"/>
                    <TextBlock x:Name="CBbPropertyNodeTName" VerticalAlignment="Center" HorizontalAlignment="Center"
                               Height="25" Padding="5"
                               Text="{Binding m_strName, Mode=TwoWay, UpdateSourceTrigger=LostFocus}"/>
                </StackPanel>-->
            </HierarchicalDataTemplate>
        </TreeView.ItemTemplate>
    </TreeView>
</UserControl>

cs

    public partial class TestTreeView : UserControl
    {
        public ObservableCollection<CBbPropertyNodeItem> itemList { get; set; } 
            = new ObservableCollection<CBbPropertyNodeItem>();
        public TestTreeView()
        {
            InitializeComponent();

            List<string> list = new List<string>();
            for (int i = 1; i < 100; i++)
            {
                list.Add(String.Format("Test {0}", i));
            }
            //My_TreeView.ItemsSource = list;

            CBbPropertyNodeItem cBbPropertyNodeItem1 = new CBbPropertyNodeItem()
            {
                Icon = "\ued96",
                Image = "/Images/folder-close.png",
                m_strName ="Test 1",
                Children = new ObservableCollection<CBbPropertyNodeItem>()
                { 
                     new CBbPropertyNodeItem()
                     {
                          Icon = "\ued96",
                          Image = "/Images/folder-close.png",
                          m_strName ="Test 1_1",
                     },
                     new CBbPropertyNodeItem()
                     {
                          Icon = "\ued96",
                          Image = "/Images/folder-close.png",
                          m_strName ="Test 1_2",
                     },
                     new CBbPropertyNodeItem()
                     {
                          Icon = "\ued96",
                          Image = "/Images/folder-close.png",
                          m_strName ="Test 1_3",
                     }
                }
            };
            CBbPropertyNodeItem cBbPropertyNodeItem2 = new CBbPropertyNodeItem()
            {
                Icon = "\ued96",
                Image = "/Images/folder-close.png",
                m_strName = "Test 2",
                Children = new ObservableCollection<CBbPropertyNodeItem>()
                {
                     new CBbPropertyNodeItem()
                     {
                          Icon = "\ued96",
                          Image = "/Images/folder-close.png",
                          m_strName ="Test 2_1",
                     },
                     new CBbPropertyNodeItem()
                     {
                          Icon = "\ued96",
                          Image = "/Images/folder-close.png",
                          m_strName ="Test 2_2",
                     },
                     new CBbPropertyNodeItem()
                     {
                          Icon = "\ued96",
                          Image = "/Images/folder-close.png",
                          m_strName ="Test 2_3",
                     }
                }
            };
            itemList.Add(cBbPropertyNodeItem1);
            itemList.Add(cBbPropertyNodeItem2);
            this.TView.SetBinding(TreeView.ItemsSourceProperty, new Binding("itemList")
            {
                Source = this
            });
        }

        private void ProductListItem_DoubleClick(object sender, MouseButtonEventArgs e)
        {
            TreeViewItem treeViewItem = sender as TreeViewItem;
            ToggleButton toggleButton = sender as ToggleButton;
            CBbPropertyNodeItem cBbPropertyNodeItem;
            if (toggleButton != null)
            {
                cBbPropertyNodeItem = toggleButton.DataContext as CBbPropertyNodeItem;
                cBbPropertyNodeItem.IsExpanded = toggleButton.IsChecked == false ? true : false;               
            }
            else
            {
                cBbPropertyNodeItem = treeViewItem.Header as CBbPropertyNodeItem;
                cBbPropertyNodeItem.IsExpanded = treeViewItem.IsExpanded == false ? true : false;
            }
            if (cBbPropertyNodeItem.IsExpanded)
            {
                cBbPropertyNodeItem.Image = "/Images/file-open.png";
                cBbPropertyNodeItem.Icon = "\ued95";
            }
            else
            {
                cBbPropertyNodeItem.Image = "/Images/folder-close.png";
                cBbPropertyNodeItem.Icon = "\ued96";
            }
        }
        private void CBbPropertyNodeName_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            CBbPropertyNodeItem cBbPropertyNodeItem =((StackPanel)sender).DataContext as CBbPropertyNodeItem;
            if (cBbPropertyNodeItem != null)
            {
                foreach (var item in itemList)
                {
                    if ((CBbPropertyNodeItem)item== cBbPropertyNodeItem)
                    {
                        item.IsExpanded = item.IsExpanded == false ? true:false;
                        if (!item.IsExpanded)
                        {
                            foreach (var items in item.Children)
                            {
                                ((CBbPropertyNodeItem)items).IsExpanded = false;
                            }
                        }
                    }
                }
            }
        }
    }

源码

https://download.csdn.net/download/qq_34581845/85945990

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值