Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 511|回复: 0

WPF - TreeView 仿VS2013解决方案资源管理器中的树状结构

[复制链接]
  • TA的每日心情
    奋斗
    2024-4-6 11:05
  • 签到天数: 748 天

    [LV.9]以坛为家II

    2034

    主题

    2092

    帖子

    70万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    705612
    发表于 2021-5-24 13:51:57 | 显示全部楼层 |阅读模式

    效果图

    先上效果图,若是你想要的效果,可以继续看下面的代码,不想浪费大家的时间。

    样式定义

    此处定义TreeView的样式,参考自MSDN,稍作修改。

    注意:在TreeViewItem控件模板定义中绑定一个数据(Level)以及一个值转换器(LevelToMarginConverter),具体定义见下部分。

    <Style x:Key="ExpandCollapseToggleStyle" TargetType="ToggleButton">
        <Setter Property="Focusable" Value="False"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="ToggleButton">
                    <Border Width="12" Height="14">
                        <Path x:Name="ExpandPath" HorizontalAlignment="Right" VerticalAlignment="Center"
                                Fill="Transparent" Stroke="#FFE6E6E6" Data="M 2 2 L 7 7 L 2 12 Z"/>
                    </Border>
                    <ControlTemplate.Triggers>
                        <MultiTrigger>
                            <MultiTrigger.Conditions>
                                <Condition Property="IsMouseOver" Value="True"/>
                                <Condition Property="IsChecked" Value="False"/>
                            </MultiTrigger.Conditions>
                            <Setter Property="Stroke" TargetName="ExpandPath" Value="#FF1BBBFA"/>
                        </MultiTrigger>
                        <Trigger Property="IsChecked" Value="True">
                            <Setter Property="Data" TargetName="ExpandPath" Value="M 1 10 L 7 3 L 7 10 Z"/>
                            <Setter Property="Fill" TargetName="ExpandPath" Value="#FFE6E6E6"/>
                        </Trigger>
                        <MultiTrigger>
                            <MultiTrigger.Conditions>
                                <Condition Property="IsMouseOver" Value="True"/>
                                <Condition Property="IsChecked" Value="True"/>
                            </MultiTrigger.Conditions>
                            <Setter Property="Stroke" TargetName="ExpandPath" Value="#FF1BBBFA"/>
                            <Setter Property="Fill" TargetName="ExpandPath" Value="#FF1BBBFA"/>
                        </MultiTrigger>
                                
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    <Style x:Key="TreeViewItemFocusVisual">
        <Setter Property="Control.Template">
            <Setter.Value>
                <ControlTemplate>
                    <Border>
                        <Rectangle Margin="0,0,0,0" StrokeThickness="5" Stroke="Black" StrokeDashArray="1 2" Opacity="0" Fill="Black"/>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    <Style x:Key="ModernTreeViewItem" TargetType="{x:Type TreeViewItem}">
        <Setter Property="Background" Value="Transparent"/>
        <Setter Property="HorizontalContentAlignment" Value="{Binding Path=HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
        <Setter Property="VerticalContentAlignment" Value="{Binding Path=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.RowDefinitions>
                            <RowDefinition Height="Auto"/>
                            <RowDefinition />
                        </Grid.RowDefinitions>
                        <Border Name="Bd" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" 
                                BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}">
                            <Grid Margin="{Binding Level, Converter={StaticResource LevelToMarginConverter}}">
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="auto"/>
                                    <ColumnDefinition />
                                </Grid.ColumnDefinitions>
                                <ToggleButton x:Name="Expander" Style="{StaticResource ExpandCollapseToggleStyle}" ClickMode="Press" HorizontalAlignment="Left"
                                                IsChecked="{Binding Path=IsExpanded, RelativeSource={RelativeSource TemplatedParent}}"/>
                                <ContentPresenter Grid.Column="1" Margin="8,0,0,0" x:Name="PART_Header" ContentSource="Header" 
                                                    HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"/>
                            </Grid>
                        </Border>
                        <ItemsPresenter x:Name="ItemsHost" Grid.Row="1"/>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsExpanded" Value="false">
                            <Setter TargetName="ItemsHost" Property="Visibility" Value="Collapsed"/>
                        </Trigger>
                        <Trigger Property="HasItems" Value="false">
                            <Setter TargetName="Expander" Property="Visibility" Value="Hidden"/>
                        </Trigger>
                        <MultiTrigger>
                            <MultiTrigger.Conditions>
                                <Condition Property="HasHeader" Value="false"/>
                                <Condition Property="Width" Value="Auto"/>
                            </MultiTrigger.Conditions>
                            <Setter TargetName="PART_Header" Property="MinWidth" Value="75"/>
                        </MultiTrigger>
                        <MultiTrigger>
                            <MultiTrigger.Conditions>
                                <Condition Property="HasHeader" Value="false"/>
                                <Condition Property="Height" Value="Auto"/>
                            </MultiTrigger.Conditions>
                            <Setter TargetName="PART_Header" Property="MinHeight" Value="19"/>
                        </MultiTrigger>
                        <Trigger Property="IsSelected" Value="true">
                            <Setter TargetName="Bd" Property="Background" 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 TargetName="Bd" Property="Background" 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>

    值转换器定义

    此转换器主要用于根据子节点的级数计算每行内容的缩进,根节点级数为1,根节点的子节点级数为2,依次类推。

    class LevelToMarginConverter : System.Windows.Data.IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            var level = (int)value;
            return new System.Windows.Thickness(8 * level + 10 * (level - 1), 0, 0, 0);
        }
                
    
        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return null;
        }
    }

    数据定义

    此处定义的TreeView空间绑定的数据。

    注意:在TreeNode类中定义了Level属性,用于指示当前节点的级数。

    public class TreeViewData
    {
        private static TreeViewData _Data = null;
    
        public static TreeViewData Data
        {
            get
            {
                if(_Data == null)
                {
                    _Data = new TreeViewData();
    
                    var rn1 = new TreeNode() { Label = "Root A", Level = 1 };
                    rn1.ChildNodes.Add(new TreeNode() { Label = "Root A - Child 1", Level = 2 });
                    rn1.ChildNodes.Add(new TreeNode() { Label = "Root A - Child 2", Level = 2 });
                    rn1.ChildNodes.Add(new TreeNode() { Label = "Root A - Child 3", Level = 2 });
                    rn1.ChildNodes.Add(new TreeNode() { Label = "Root A - Child 4", Level = 2 });
                    rn1.ChildNodes.Add(new TreeNode() { Label = "Root A - Child 5", Level = 2 });
    
                    var rn2 = new TreeNode() { Label = "Root B", Level = 1 };
                    rn2.ChildNodes.Add(new TreeNode() { Label = "Root B - Child 1", Level = 2 });
    
                    var rn21 = new TreeNode() { Label = "Root B - Child 2", Level = 2 };
                    rn21.ChildNodes.Add(new TreeNode() { Label = "Root B - Child 2 - Child 1", Level = 3 });
                    rn21.ChildNodes.Add(new TreeNode() { Label = "Root B - Child 2 - Child 2", Level = 3 });
                    rn2.ChildNodes.Add(rn21);
                    rn2.ChildNodes.Add(new TreeNode() { Label = "Root B - Child 3", Level = 2 });
                    rn2.ChildNodes.Add(new TreeNode() { Label = "Root B - Child 4", Level = 2 });
                    rn2.ChildNodes.Add(new TreeNode() { Label = "Root B - Child 5", Level = 2 });
    
    
    
                    var rn3 = new TreeNode() { Label = "Root C", Level = 1 };
                    rn3.ChildNodes.Add(new TreeNode() { Label = "Root C - Child 1", Level = 2 });
                    rn3.ChildNodes.Add(new TreeNode() { Label = "Root C - Child 2", Level = 2 });
                    rn3.ChildNodes.Add(new TreeNode() { Label = "Root C - Child 3", Level = 2 });
                    rn3.ChildNodes.Add(new TreeNode() { Label = "Root C - Child 4", Level = 2 });
                    rn3.ChildNodes.Add(new TreeNode() { Label = "Root C - Child 5", Level = 2 });
    
                    _Data.RootNodes.Add(rn1);
                    _Data.RootNodes.Add(rn2);
                    _Data.RootNodes.Add(rn3);
                }
                return _Data;
            }
        }
    
        private System.Collections.ObjectModel.ObservableCollection<TreeNode> _RootNodes = null;
    
        public IList<TreeNode> RootNodes { get { return _RootNodes ?? (_RootNodes = new System.Collections.ObjectModel.ObservableCollection<TreeNode>()); } }
    
        public class TreeNode
        {
            public string Label { get; set; }
    
            public int Level { get; set; }
    
            private System.Collections.ObjectModel.ObservableCollection<TreeNode> _ChildNodes = null;
    
            public IList<TreeNode> ChildNodes { get { return _ChildNodes ?? (_ChildNodes = new System.Collections.ObjectModel.ObservableCollection<TreeNode>()); } }
        }
    }

    应用样式

    <TreeView ItemsSource="{Binding Source={x:Static data:TreeViewData.Data}, Path=RootNodes}"
              HorizontalContentAlignment="Stretch" Background="#FF252526" Width="300" ItemContainerStyle="{StaticResource ModernTreeViewItem}">
        <TreeView.ItemTemplate>
            <HierarchicalDataTemplate DataType="{x:Type data:TreeViewData+TreeNode}" ItemsSource="{Binding ChildNodes}">
                <Grid Height="32">
                    <TextBlock Text="{Binding Label}" VerticalAlignment="Center" Foreground="#FFE6E6E6" FontSize="13"/>
                </Grid>
            </HierarchicalDataTemplate>
        </TreeView.ItemTemplate>
    </TreeView>

     

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-5-18 15:02 , Processed in 0.063154 second(s), 29 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表