WPF之TreeList的实现方法(一)

做项目的时候根据需求,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

 

posted @ 2013-09-09 11:58  li-peng  阅读(7837)  评论(14编辑  收藏  举报