关于WPF TreeView我的一点心得

首先我的样式操作:

文件名是:TreeViewStyle

csharp 复制代码
 <Style x:Key="DefaultTreeViewItem" TargetType="{x:Type TreeViewItem}">
        <Setter Property="MinHeight" Value="40" />
        <Setter Property="Foreground" Value="#333233" />
        <!--<Setter Property="Background" Value="#484C7F" />-->
        <Setter Property="SnapsToDevicePixels" Value="True" />
        <Setter Property="Cursor" Value="Hand" />
        <Setter Property="Margin" Value="5,0,5,0" />
        <Setter Property="FontSize" Value="14" />
        <!--<EventSetter Event="PreviewMouseLeftButtonDown" Handler="TreeViewItem_Click" />-->
        <!--<Setter Property="local:ControlAttachProperty.FIconSize" Value="19"/>-->
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type TreeViewItem}">
                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition/>
                            <RowDefinition/>
                        </Grid.RowDefinitions>
                        <Border x:Name="Bd" Margin="3" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" CornerRadius="4"
                                BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}"
                                MinHeight="{TemplateBinding MinHeight}" UseLayoutRounding="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}">
                            <!--多层级间隔,暂缓-->
                            <!--<Grid Margin="{Binding Converter={StaticResource LengthConverter}, RelativeSource={x:Static RelativeSource.TemplatedParent}}"-->
                            <Grid Margin="{TemplateBinding Margin}">
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="15" />
                                    <ColumnDefinition Width="*" />
                                    <ColumnDefinition MinWidth="18" Width="Auto" />
                                    <ColumnDefinition Width="15" />
                                </Grid.ColumnDefinitions>
                                <!--展开收缩按钮-->
                                <ToggleButton x:Name="ExpanderBtn" Grid.Column="2" HorizontalContentAlignment="Stretch"
                                              IsChecked="{Binding Path=IsExpanded, RelativeSource={x:Static RelativeSource.TemplatedParent}, Mode=TwoWay}"
                                              ClickMode="Press" >
                                    <ToggleButton.Template>
                                        <ControlTemplate TargetType="ToggleButton">
                                            <Border>
                                                <ContentPresenter VerticalAlignment="Center" HorizontalAlignment="Center" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
                                            </Border>
                                        </ControlTemplate>
                                    </ToggleButton.Template>
                                    <ToggleButton.Content>
                                        <TextBlock x:Name="ExpanderIcon" Foreground="#333233" FontFamily="../../Fonts/MyFonts/#iconfont" Grid.Column="1" Text="&#xf104;" FontSize="18" />
                                        <!--FontSize="{TemplateBinding local:ControlAttachProperty.FIconSize}" />-->
                                    </ToggleButton.Content>
                                </ToggleButton>
                                <!--内容-->
                                <ContentPresenter x:Name="PART_Header" Grid.Column="1" ContentSource="Header"
                                                  SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                                                  HorizontalAlignment="Left"
                                                  VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                            </Grid>
                        </Border>
                        <!--<ItemsPresenter Grid.Row="1" Margin="18,0,0,0" x:Name="ItemsHost"  SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />-->

                        <Border x:Name="MianBan" Grid.Row="1" CornerRadius="4" Margin="5,0,5,0">
                            <ItemsPresenter  x:Name="ItemsHost"/>
                        </Border>
                        <!--Margin="18,0,0,0"-->
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsExpanded" Value="False">
                            <Setter TargetName="ItemsHost" Property="Visibility" Value="Collapsed" />
                        </Trigger>
                        <Trigger Property="IsExpanded" Value="True">
                            <!--<Setter TargetName="ExpanderIcon" Property="Text" Value="&#xe62d;" />-->
                            <Setter TargetName="ExpanderIcon" Property="Text" Value="&#xf107;" />
                        </Trigger>
                        <Trigger Property="HasItems" Value="False">
                            <Setter TargetName="ExpanderIcon" Property="Visibility" Value="Hidden" />
                        </Trigger>
                        <!--<Trigger Property="IsMouseOver" Value="True">
                            <Setter Property="Background" TargetName="Bd" Value="#60636C" />
                            <Setter Property="Foreground" TargetName="ExpanderIcon" Value="#FFFFCC" />
                            <Setter Property="Foreground" Value="#FFFFCC" />
                        </Trigger>-->
                        <!--<DataTrigger Binding="{Binding IsGrouping}" Value="1">
                            <Setter Property="Background" TargetName="MianBan" Value="#E6E7EF" />
                        </DataTrigger>
                        <DataTrigger Binding="{Binding IsGrouping}" Value="2">
                            <Setter Property="Background" TargetName="MianBan" Value="#CFD0D7" />
                        </DataTrigger>-->
                        <!--<Trigger Property="IsSelected" Value="True">
                            <Setter Property="Background" TargetName="Bd" Value="#60636C" />
                            <Setter Property="Foreground" TargetName="ExpanderIcon" Value="#F9DEC1" />
                            <Setter Property="Foreground" Value="#F9DEC1" />
                        </Trigger>-->

                        <!--<MultiTrigger>
                                    <MultiTrigger.Conditions>
                                        <Condition Property="IsSelected" Value="True" />
                                        <Condition Property="Selector.IsSelectionActive" Value="True" />
                                    </MultiTrigger.Conditions>
                                    <Setter Property="Background" TargetName="Bd" Value="#60636C" />
                                    <Setter Property="Foreground" TargetName="ExpanderIcon" Value="red" />
                                    <Setter Property="Foreground" Value="#F9DEC1" />
                                </MultiTrigger>-->
                        <MultiTrigger>
                            <MultiTrigger.Conditions>
                                <Condition Property="IsSelected" Value="True" />
                                <!--<Condition Property="Selector.IsSelectionActive" Value="True" />-->
                            </MultiTrigger.Conditions>
                            <Setter Property="Background" TargetName="Bd" Value="#60636C" />
                            <Setter Property="Foreground" TargetName="ExpanderIcon" Value="#F9DEC1" />
                            <Setter Property="Foreground" Value="#F9DEC1" />
                        </MultiTrigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>


    <Style x:Key="TypeTreeStyle" TargetType="TreeView">
        <Setter Property="ScrollViewer.CanContentScroll" Value="True" />
        <Setter Property="VirtualizingStackPanel.IsVirtualizing" Value="True"></Setter>
        <Setter Property="VirtualizingStackPanel.VirtualizationMode" Value="Recycling" />
        <Setter Property="ScrollViewer.IsDeferredScrollingEnabled" Value="False" />
        <Setter Property="Background"  Value="Transparent"/>
        <Setter Property="Padding" Value="0"/>
        <!--<EventSetter Event="PreviewMouseLeftButtonDown" Handler="TreeViewItem_PreviewMouseLeftButtonDown" />-->
        <Setter Property="ItemContainerStyle" Value="{StaticResource DefaultTreeViewItem}"></Setter>
        <Setter Property="ItemsPanel">
            <Setter.Value>
                <ItemsPanelTemplate>
                    <VirtualizingStackPanel IsItemsHost="True" IsVirtualizing="True" VirtualizationMode="Recycling" Margin="0"/>
                </ItemsPanelTemplate>
            </Setter.Value>
        </Setter>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="TreeView">
                    <ScrollViewer Padding="4" Focusable="False" CanContentScroll="False">
                        <ItemsPresenter/>
                    </ScrollViewer>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    <Style x:Key="TypeNode" TargetType="TreeViewItem">
        <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}"/>   <!--如果有这个属性可以通过这属性获取到是否选择的状态-->
        <Setter Property="FontWeight" Value="Normal"/>
        <Setter Property="IsExpanded" Value="True"/> <!--设置直接展开-->
        <Style.Triggers>
            <Trigger Property="IsSelected" Value="True">
                <Setter Property="FontWeight" Value="Bold"/>
                <Setter Property="Background" Value="Brown"/>
            </Trigger> 
        </Style.Triggers>
    </Style>
    <HierarchicalDataTemplate x:Key="TypeTreeGroup" ItemsSource="{Binding Children}">
        <StackPanel Orientation="Horizontal">
            <!--<Image Source="/WpfTutorialSamples;component/Images/user.png" Margin="0,0,5,0" />-->
            <!--当然这里可以用Image数据来操作 也可以用binding来绑定对应的图片标示-->
            <TextBlock Text="{Binding ThisName}" FontSize="13"/>
        </StackPanel>
    </HierarchicalDataTemplate>

我的界面配置:

csharp 复制代码
<Window.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="/Styles/TreeViewStyle.xaml"></ResourceDictionary>
                <ResourceDictionary Source="/Styles/ButtonSetStyle.xaml"></ResourceDictionary>
                <!--<ResourceDictionary Source="../../Assets/style/ScrollBarThumbStyle.xaml"></ResourceDictionary>-->
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Window.Resources>

然后 关于 treeview 的配置是

csharp 复制代码
<TreeView Name="MainTree"  ItemsSource="{Binding TypeTree}" Style="{StaticResource TypeTreeStyle}" ItemContainerStyle="{StaticResource TypeNode}" ItemTemplate="{StaticResource TypeTreeGroup}" SelectedItemChanged="MainTree_SelectedItemChanged"> 
 </TreeView>

这个配置必须要 绑定ThisName textbolck 的text 显示 然后

ItemsSource="{Binding Children} 对应就是属性children数据

其中 属性为:

csharp 复制代码
   /// <summary>
    /// 栏目表
    /// </summary>
    public  class MainItemInfos
    {
              
        /// <summary>
        /// 
        /// </summary> 
        [Description("")]
        public int  Id { get; set; } 
        /// <summary>
        /// 编号
        /// </summary> 
        [Description("编号")]
        public string ThisNo { get; set; } 
        /// <summary>
        /// 父id
        /// </summary> 
        [Description("父id")]
        public int  PId { get; set; } 
        /// <summary>
        /// 当前地址
        /// </summary> 
        [Description("当前地址")]
        public string  ThitPath { get; set; } 
        /// <summary>
        /// 当前名称
        /// </summary> 
        [Description("当前名称")]
        public string  ThisName { get; set; } 
        /// <summary>
        /// 是否启用
        /// </summary> 
        [Description("是否启用")]
        public bool  IsUsed { get; set; } 
        /// <summary>
        /// 数据类型(0,首页,1 栏目,3根栏目)
        /// </summary> 
        [Description("数据类型(0 顶级页,1首页,2 栏目,3根栏目)")]
        public EItemType  PathType { get; set; } 
        /// <summary>
        /// 
        /// </summary> 
        [Description("")]
        public DateTime  CreateDate { get; set; } 
        /// <summary>
        /// 
        /// </summary> 
        [Description("")]
        public DateTime  Updated { get; set; }
        /// <summary>
        /// 当前
        /// </summary>
        public MainItemInfos ParentInfo { get; set; }

        /// <summary>
        /// 当前所有子数据
        /// </summary>
        public ObservableCollection<MainItemInfos> Children { get; set; }
    }

另外 从数据库获取来后的list操作

csharp 复制代码
 /// <summary>
        /// 获取树结构下所有数据
        /// </summary>
        /// <param name="ThisInfo"></param>
        /// <param name="ThisListAll"></param>
        /// <param name="RetureInfolist"></param>
        public void GetTreeNodeModel(MainItemInfos ThisInfo, List<MainItemInfos> ThisListAll, ref List<MainItemInfos> RetureInfolist)
        {
            List<MainItemInfos> ListOut = new List<MainItemInfos>();
            IEnumerable<MainItemInfos> ListThisMains = ThisListAll.Where(x => x.PId == ThisInfo.Id);
            if (ListThisMains != null && ListThisMains.Count() > 0)
            {
                ThisInfo.Children = new System.Collections.ObjectModel.ObservableCollection<MainItemInfos>(ListThisMains);
                RetureInfolist.Add(ThisInfo);
                foreach (MainItemInfos OneInfo in ThisInfo.Children)
                { 
                    OneInfo.ParentInfo = ThisInfo;
                    GetChildren(OneInfo, ThisListAll);
                    //GetTreeNodeModel(OneInfo, ThisListAll, ref RetureInfolist);
                }
            }
        }
        /// <summary>
        /// 子目录下的文件(这样只有一个List可以只有一个树结构)一一更新
        /// </summary>
        /// <param name="ThisModel"></param>
        /// <param name="ListAll"></param>
        public void GetChildren(MainItemInfos ThisModel,List<MainItemInfos> ListAll)
        {
            if (ListAll != null )
            {
                IEnumerable<MainItemInfos> ListThisMains = ListAll.Where(x => x.PId == ThisModel.Id); 
                if (ListThisMains!=null &&  ListThisMains.Count() > 0)
                {
                    ThisModel.Children = new System.Collections.ObjectModel.ObservableCollection<MainItemInfos>(ListThisMains) ;
                    foreach (MainItemInfos OneItem in ThisModel.Children)
                    {
                        GetChildren(OneItem,ListAll);
                    }
                }
                
            }
          
        }
        /// <summary>
        /// 刷新树结构
        /// </summary>
        public void ReflashNodes()
        {
            List<MainItemInfos> ListDB = new DAL.DALMainItemInfos().QueryList().ToList();
            MainItemInfos ThisZongInfos = ListDB.Where(x => x.PathType == 0).FirstOrDefault();
            ListDB.Remove(ThisZongInfos);
            List<MainItemInfos> ListBinding = new List<MainItemInfos>();
            GetTreeNodeModel(ThisZongInfos, ListDB, ref ListBinding);
            if (ListBinding != null)
            {
                MainTree.ItemsSource = ListBinding;
            }
        }
相关推荐
Clank的游戏栈2 小时前
Unity多线程渲染指令队列设计与集成技术详解
windows·unity·游戏引擎
sukida1006 小时前
BIOS主板(非UEFI)安装fedora42的方法
linux·windows·fedora
界面开发小八哥8 小时前
界面控件DevExpress WPF v25.1预览 - 支持Windows 11系统强调色
windows·wpf·界面控件·devexpress·ui开发·.net 9
军训猫猫头10 小时前
89.WPF 中实现便捷的数字输入框:DecimalUpDown 控件的使用 WPF例子 C#例子.
开发语言·c#·wpf
岫珩12 小时前
“由于启动计算机时出现了页面文件配置问题,Windows在你的计算机上创建了一个临时页面文件。。。”的问题解决
windows
Pasregret12 小时前
缓存与数据库一致性深度解析与解决方案
数据库·缓存·wpf
李菠菜13 小时前
解决Windows系统下Git克隆时报错“unable to checkout working tree”的方法详解
windows·git
子非衣17 小时前
Windows云主机远程连接提示“出现了内部错误”
服务器·windows
剁椒排骨18 小时前
win11什么都不动之后一段时间黑屏桌面无法显示,但鼠标仍可移动,得要熄屏之后才能进入的四种解决方法
运维·windows·经验分享·计算机外设·win11·win10
李菠菜18 小时前
Windows Terminal 集成 Git Bash 的简洁配置指南
windows·git