WPF之TreeList的实现方法(一)

简介: 做项目的时候根据需求,WPF现有的控件不能完全满足我们的需求, 很多时候我们需要对现有的控件做一下加工。 最简单的我们可能会把Tree转换成List形式有的叫Grid形式就像下图一样 今天我先做一个完全用样式加工的例子,有时间我再把它做深加工写成一下通能形式 我们要先把treeView重...

做项目的时候根据需求,WPF现有的控件不能完全满足我们的需求,

很多时候我们需要对现有的控件做一下加工。

最简单的我们可能会把Tree转换成List形式有的叫Grid形式就像下图一样

今天我先做一个完全用样式加工的例子,有时间我再把它做深加工写成一下通能形式

我们要先把treeView重写一下

public class TreeListView : TreeView
    {
        //这两个默认的是TreeViewItem
        protected override DependencyObject GetContainerForItemOverride()//创建或标识用于显示指定项的元素。 
        {
            return new TreeListViewItem();
        }

        protected override bool IsItemItsOwnContainerOverride(object item)//确定指定项是否是(或可作为)其自己的 ItemContainer
        {
            //return item is TreeListViewItem;
            bool _isTreeLVI = item is TreeListViewItem;
            return _isTreeLVI;
        }
    }

    public class TreeListViewItem : TreeViewItem
    {
        /// <summary>
        /// hierarchy 
        /// </summary>
        public int Level
        {
            get
            {
                if (_level == -1)
                {
                    TreeListViewItem parent =
                        ItemsControl.ItemsControlFromItemContainer(this) as TreeListViewItem;//返回拥有指定的容器元素中 ItemsControl 。 
                    _level = (parent != null) ? parent.Level + 1 : 0;
                }
                return _level;
            }
        }


        protected override DependencyObject GetContainerForItemOverride()
        {
            return new TreeListViewItem();
        }

        protected override bool IsItemItsOwnContainerOverride(object item)
        {
            //return item is TreeListViewItem;
            bool _isITV = item is TreeListViewItem;
            return _isITV;
        }

        private int _level = -1;
    }

上边是对TreeView的重写,因为TreeView是有层级关系的我们做的重写就把它的层级返回来

我们还要有一个列宽的转换

/// <summary>
    ///  
    ///  
    /// </summary>
    public class LevelToIndentConverter : IValueConverter
    {
        public object Convert(object o, Type type, object parameter, CultureInfo culture)
        {
            return new Thickness((int)o * c_IndentSize, 0, 0, 0);
        }

        public object ConvertBack(object o, Type type, object parameter, CultureInfo culture)
        {
            throw new NotSupportedException();
        }

        private const double c_IndentSize = 25.0;
    }

 

下边是样式和使用方法

我们是把TreeView的样式加上了GridViewColumnCollection实现 的这个TreeView和ListView一样有标头和列

前台页面

<Window x:Class="TreeViewListDemoT.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:l="clr-namespace:TreeViewListDemoT"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        
        <Style x:Key="ExpandCollapseToggleStyle" TargetType="{x:Type ToggleButton}">
            <Setter Property="Focusable"  Value="False"/>
            <Setter Property="Width"      Value="19"/>
            <Setter Property="Height"     Value="13"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ToggleButton}">
                        <Border Width="19"  Height="13"  Background="Transparent">
                            <Border Width="9" Height="9"   BorderThickness="1"    BorderBrush="#FF7898B5"   CornerRadius="1"  SnapsToDevicePixels="true">
                                <Border.Background>
                                    <LinearGradientBrush StartPoint="0,0"  EndPoint="1,1">
                                        <LinearGradientBrush.GradientStops>
                                            <GradientStop Color="White"     Offset=".2"/>
                                            <GradientStop Color="#FFC0B7A6" Offset="1"/>
                                        </LinearGradientBrush.GradientStops>
                                    </LinearGradientBrush>
                                </Border.Background>
                                <Path x:Name="ExpandPath" Margin="1,1,1,1" Fill="Black"
                      Data="M 0 2 L 0 3 L 2 3 L 2 5 L 3 5 L 3 3 L 5 3 L 5 2 L 3 2 L 3 0 L 2 0 L 2 2 Z"/>
                            </Border>
                        </Border>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsChecked" Value="True">
                                <Setter Property="Data" TargetName="ExpandPath" Value="M 0 2 L 0 3 L 5 3 L 5 2 Z"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
        <l:LevelToIndentConverter x:Key="LevelToIndentConverter"/>

        <DataTemplate x:Key="CellTemplate_Name">
            <DockPanel>
                <ToggleButton x:Name="Expander" Style="{StaticResource ExpandCollapseToggleStyle}" Margin="{Binding Level,
                             Converter={StaticResource LevelToIndentConverter},RelativeSource={RelativeSource AncestorType={x:Type l:TreeListViewItem}}}"
                             IsChecked="{Binding Path=IsExpanded,RelativeSource={RelativeSource AncestorType={x:Type l:TreeListViewItem}}}" ClickMode="Press"/>
                <TextBlock Text="{Binding Name}"/>
            </DockPanel>
            <DataTemplate.Triggers>
                <DataTrigger Binding="{Binding Path=HasItems,RelativeSource={RelativeSource AncestorType={x:Type l:TreeListViewItem}}}" Value="False">
                    <Setter TargetName="Expander" Property="Visibility" Value="Hidden"/>
                </DataTrigger>
            </DataTemplate.Triggers>
        </DataTemplate>

        <GridViewColumnCollection x:Key="gvcc">
            <GridViewColumn Header="Name" CellTemplate="{StaticResource CellTemplate_Name}" />
            <GridViewColumn Header="Age"      DisplayMemberBinding="{Binding Age}" Width="60" />
            <GridViewColumn Header="Sex"      DisplayMemberBinding="{Binding Sex}" Width="60"/>
        </GridViewColumnCollection>

        <Style TargetType="{x:Type l:TreeListViewItem}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type l:TreeListViewItem}">
                        <StackPanel>
                            <Border Name="Bd"
                              Background="{TemplateBinding Background}"
                              BorderBrush="{TemplateBinding BorderBrush}"
                              BorderThickness="{TemplateBinding BorderThickness}"
                              Padding="{TemplateBinding Padding}">
                                <GridViewRowPresenter x:Name="PART_Header" 
                                      Content="{TemplateBinding Header}" 
                                      Columns="{StaticResource gvcc}" />
                            </Border>
                            
                            <ItemsPresenter x:Name="ItemsHost" />
                        </StackPanel>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsExpanded" Value="false">
                                <Setter TargetName="ItemsHost" Property="Visibility"               Value="Collapsed"/>
                            </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>

        <Style TargetType="{x:Type l:TreeListView}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type l:TreeListView}">
                        <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
                            <DockPanel>
                                <GridViewHeaderRowPresenter Columns="{StaticResource gvcc}" DockPanel.Dock="Top"/>
                                <Border BorderThickness="2">
                                <ItemsPresenter/>
                                </Border>
                            </DockPanel>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
        
        
    </Window.Resources>
    <Grid>
        <l:TreeListView x:Name="_list" ItemsSource="{Binding Children}"  BorderThickness="2">
            <l:TreeListView.ItemTemplate >
                <HierarchicalDataTemplate ItemsSource="{Binding Children}" >
                    <Border BorderThickness="2" BorderBrush="Yellow" CornerRadius="0" Margin="1"  x:Name="back" MinWidth="70"
                                DataContext="{Binding}" >
                        <StackPanel Orientation="Horizontal" Margin="2">
                            <TextBlock Text="{Binding Text}" Margin="2 0"/>
                        </StackPanel>
                    </Border>
                </HierarchicalDataTemplate>
                
            </l:TreeListView.ItemTemplate>
            
        </l:TreeListView>
    </Grid>
</Window>

 后台代码

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace TreeViewListDemoT
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            ObjForTest root = new ObjForTest();
            ObjForTest depart = new ObjForTest("Department", null, "");
            ObjForTest c1 = new ObjForTest( "li", 45, "M");
            ObjForTest c2 = new ObjForTest( "xu", 30, "W");
            ObjForTest c3 = new ObjForTest("zhang", 22, "M");
            ObjForTest cc1 = new ObjForTest( "shen", 30, "M");
            ObjForTest cc2 = new ObjForTest( "zhao", 18, "W");
            ObjForTest cc3 = new ObjForTest( "wang", 32, "M");
            ObjForTest ccc1 = new ObjForTest( "qian", 20, "W");
            root.Children.Add(depart);
            depart.Children.Add(c1);
            depart.Children.Add(c2);
            depart.Children.Add(c3);
            c1.Children.Add(cc1);
            c2.Children.Add(cc2);
            c3.Children.Add(cc3);
            cc1.Children.Add(ccc1);
            this._list.ItemsSource = root.Children;
        }
    }

    public class ObjForTest 
    {
        public ObjForTest() { }
        public ObjForTest( string name, int? age, string sex)
        {
            
            this._sex = sex;
            this._age = age;
            this._name = name;
            
        }
        private string _name;
        private int? _age;
        private string _sex;
       

        public string Sex 
        { 
            get { return this._sex; } 
            set { this._sex = value; } 
        }
        public int? Age 
        { 
            get { return this._age; }
            set { this._age = value; }
        }
      
        public string Name
        {
            get { return _name; }
            set
            {
                _name = value;

            }
        }

        private ObservableCollection<ObjForTest> _children = new ObservableCollection<ObjForTest>();
        public ObservableCollection<ObjForTest> Children
        {
            get { return _children; }
        }


     
    }
}

 

 最后给代码下载 TreeViewListDemoT.rar

 

目录
相关文章
|
C#
WPF 遍历DataTemplate(获取所有控件)
原文:WPF 遍历DataTemplate(获取所有控件) 情况1:在设定DataTemplate的Name,并且他是在前台表示时,获取DataTemplate里的指定控件。
1995 0
|
3月前
|
前端开发 编译器 C#
【WPF】聊聊WPF中INotifyPropertyChanged [TOC]
【WPF】聊聊WPF中INotifyPropertyChanged [TOC]
27 0
|
4月前
|
数据可视化 API C#
|
数据可视化 C#
WPF技术之TreeView控件
WPF TreeView控件是一个用于显示分层数据的控件,类似于文件浏览器中的目录结构。
155 0
|
C#
Seaching TreeVIew WPF
原文:Seaching TreeVIew WPF 项目中有一个树形结构的资源,需要支持搜索功能,搜索出来的结果还是需要按照树形结构展示,下面是简单实现的demo。 1.首先创建TreeViewItem的ViewModel,一般情况下,树形结构都包含DisplayName,Deepth,Parent...
826 0
|
C#
关于WPF中Popup中的一些用法的总结
原文:关于WPF中Popup中的一些用法的总结   Popup控件是一个常用的非常有用的控件,顾明思义就是弹出式控件,首先我们来看看MSDN对它的解释吧,表示具有内容的弹出窗口,这个是非常重要的控件,我们看看它的继承关系吧:  System.
1484 0
|
C#
【WPF】拖拽ListBox中的Item
原文:【WPF】拖拽ListBox中的Item 整理了两个关于WPF拖拽ListBox中的Item的功能。项目地址 https://github.com/Guxin233/WPF-DragItemInListBox 需求一: 两个ListBox,拖拽其中一个ListBox的Item,放置到另一个ListBox中。
1603 0
Devexpress treelist 控件属性大全
属性列表 1、OptionsSelection: EnableAppearanceForcusedCell:选中的Cell的Appearance设置是否可用。默认为True; EnableAppearanceForcusedRow:选中的Node的Appearance设置是否可用。
1730 0
|
C#
WPF TreeView HierarchicalDataTemplate
原文 WPF TreeView HierarchicalDataTemplate   ...
1657 0
|
C#
WPF使用HierarchicalDataTemplate绑定Dictionary生成TreeView
原文:WPF使用HierarchicalDataTemplate绑定Dictionary生成TreeViewDictionary中的CustomeType是一个集合,将其绑定生成一棵树,树的第一层节点是Dictionary的Key,第二层是CustomeType集合,所有代码用XAML实现。
1522 0