WPFTreeGrid(树形展开的表格)
⼀直都想要个树形展开的表格 像这样的
今天⼼⾎来潮就简单做了个TreeGrid 喜欢的同学可以下载下去⾃⼰研究下,其实也⽐较简单主要就是TreeView TreeViewItem再配合GridViewHeaderRowPresenter、GridViewRowPresenter、GridViewColumnCollection定制style基本上就可以实现以上效果
本⽂中涉及⼤量模板,绑定等知识,如果刚刚⼊门还没有了解以上知识的同学可以先补下课,然后再来看,以免浪费时间。
闲话不多说,直接上代码:
前台代码 MainWindow.xaml
<Window x:Class="TreeGrid.MainWindow"
xmlns="schemas.microsoft/winfx/2006/xaml/presentation"
xmlns:x="schemas.microsoft/winfx/2006/xaml"
xmlns:local="clr-namespace:TreeGrid"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<local:LevelToMarginConverter x:Key="LevelToIndentConverter"/>
<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>
<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>
<DataTemplate x:Key="CellTemplate_Name">
<DockPanel>
<ToggleButton x:Name="Expander"
Style="{StaticResource ExpandCollapseToggleStyle}"
Margin="{Binding Level,Converter={StaticResource LevelToIndentConverter}}" IsChecked="{Binding Path=IsExpanded,
RelativeSource={RelativeSource
AncestorType=
{x:Type TreeViewItem}}}"
ClickMode="Press"/>
<TextBlock Text="{Binding Name}"/>
</DockPanel>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Path=HasItems,
RelativeSource={RelativeSource
AncestorType={x:Type TreeViewItem}}}"
Value="False">
<Setter TargetName="Expander"
Property="Visibility"
Value="Hidden"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
<GridViewColumnCollection x:Key="gvcc">
<GridViewColumn Header="Name"gridview不显示
CellTemplate="{StaticResource CellTemplate_Name}" />
<GridViewColumn Header="JobTitle"
DisplayMemberBinding="{Binding JobTitle}" Width="60"/>
<GridViewColumn Header="Age"
DisplayMemberBinding="{Binding Age}" Width="60" />
<GridViewColumn Header="Sex"
DisplayMemberBinding="{Binding Sex}" Width="60"/>
</GridViewColumnCollection>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TreeViewItem}">
<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>
<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 TreeView}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TreeView}">
<Border BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<DockPanel>
<GridViewHeaderRowPresenter Columns="{StaticResource gvcc}"
DockPanel.Dock="Top"/>
<ItemsPresenter/>
</DockPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<TreeView Name="_list" Margin="0" BorderThickness="0" VerticalAlignment="Stretch" Background="Transparent" ItemsSource="{Binding Children}" > <TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Children}">
<Border CornerRadius="0" Margin="1" x:Name="back" MinWidth="70"
Background="Transparent" DataContext="{Binding}" >
<StackPanel Orientation="Horizontal" Margin="2">
<TextBlock Text="{Binding Text}" Margin="2 0"/>
</StackPanel>
</Border>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</Grid>
</Window>
Window.Resources⾥⾯是所⽤到的style和资源,其实整个窗⼝⾥⾯就只有⼀个TreeView在codebehind绑定⼀个对象的Children属性。这⾥的treeview对象的绑定涉及到HierarchicalDataTemplate它是⼀个递归的数据模板。⽽在resources⾥⾯值得注意的是⼏个地⽅
1. <local:LevelToMarginConverter x:Key="LevelToIndentConverter"/> 这句是在定义⼀个Converter资源,因为我是使⽤绑定对象的level值来绑定前台的缩进⼤⼩,但是level属性是int型的 要转换为margin的thickness类型,所以我会⽤到⼀个继承⾃IValueConverter的LevelToMarginConverter 的类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
namespace TreeGrid
{
public class LevelToMarginConverter : 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 = 15.0;
}
}
2.TreeViewItem的style中GridViewRowPresenter是⽤来显⽰⾃⾝的值,itemspresernter是⽤来显⽰树形下级内容的
<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>
3.TreeView的style中 GridViewHeaderRowPresenter⽤来显⽰表头,ItemsPresenter⽤来显⽰TreeViewITem的列表
<ControlTemplate TargetType="{x:Type TreeView}">
<Border BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<DockPanel>
<GridViewHeaderRowPresenter Columns="{StaticResource gvcc}"
DockPanel.Dock="Top"/>
<ItemsPresenter/>
</DockPanel>
</Border>
</ControlTemplate>
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论