做項目的時候根據需求,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
