程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> WPF TreeGrid(樹形展開的表格)

WPF TreeGrid(樹形展開的表格)

編輯:C#入門知識

一直都想要個樹形展開的表格 像這樣的

 

今天心血來潮就簡單做了個TreeGrid 喜歡的同學可以下載下去自己研究下,其實也比較簡單主要就是TreeView TreeViewItem再配合GridViewHeaderRowPresenter、GridViewRowPresenter、GridViewColumnCollection定制style基本上就可以實現以上效果

本文中涉及大量模板,綁定等知識,如果剛剛入門還沒有了解以上知識的同學可以先補下課,然後再來看,以免浪費時間。

閒話不多說,直接上代碼:

前台代碼 MainWindow.xaml

[csharp] 
<Window x:Class="TreeGrid.MainWindow" 
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x="http://schemas.microsoft.com/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> 
                        <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> 
 
        <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"   
                      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> 
                        <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 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 的類

[csharp]
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是用來顯示樹形下級內容的
[csharp] 
<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的列表
[csharp]
<span>      </span><ControlTemplate TargetType="{x:Type TreeView}"> 
                        <Border BorderBrush="{TemplateBinding BorderBrush}" 
                    BorderThickness="{TemplateBinding BorderThickness}"> 
                            <DockPanel> 
                                <GridViewHeaderRowPresenter Columns="{StaticResource gvcc}" 
                                            DockPanel.Dock="Top"/> 
                                <ItemsPresenter/> 
                            </DockPanel> 
                        </Border> 
                    </ControlTemplate> 


codebehind代碼如下
[csharp]
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
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; 
using System.ComponentModel; 
using System.Collections.ObjectModel; 
 
namespace TreeGrid 

    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window 
    { 
        public MainWindow() 
        { 
            InitializeComponent(); 
            ObjForTest root = new ObjForTest("root", "root",0,"",0); 
            ObjForTest c1 = new ObjForTest("CEO", "Leo",45,"M",1); 
            ObjForTest c2 = new ObjForTest("CFO", "Tami",46,"FM",1); 
            ObjForTest c3 = new ObjForTest("COO", "Jack",47,"M",1); 
            ObjForTest cc1 = new ObjForTest("Manager", "John", 30, "M", 2); 
            ObjForTest cc2 = new ObjForTest("Manager", "Lee", 31, "FM", 2); 
            ObjForTest cc3 = new ObjForTest("Manager", "Chris", 32, "M", 2); 
            ObjForTest ccc1 = new ObjForTest("Worker", "Evan", 25,"FM",3); 
            root.Children.Add(c1); 
            root.Children.Add(c2); 
            root.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 : INotifyPropertyChanged 
    { 
        public ObjForTest(string title, string name,int age,string sex,int level) 
        { 
            this._jobTitle = title; 
            this._sex = sex; 
            this._age = age; 
            this._name = name; 
            this._level = level; 
        } 
        private string _name; 
        private int _age; 
        private string _sex; 
        private int _level; 
        private string _jobTitle; 
 
        public string Sex { get { return this._sex; } set { this._sex = value; } } 
        public int Age { get { return this._age; } set { this._age = value; } } 
        public int Level 
        { 
            get  
            {  
                return this._level; 
            } 
            set 
            { 
                _level = value; 
                if (PropertyChanged != null) 
                    PropertyChanged(this, new PropertyChangedEventArgs("Level")); 
            } 
        } 
        public string JobTitle 
        { 
            get { return _jobTitle; } 
            set 
            { 
                _jobTitle = value; 
                if (PropertyChanged != null) 
                    PropertyChanged(this, new PropertyChangedEventArgs("JobTitle")); 
            } 
        } 
        public string Name 
        { 
            get { return _name; } 
            set 
            { 
                _name = value; 
                if (PropertyChanged != null) 
                    PropertyChanged(this, new PropertyChangedEventArgs("Name")); 
            } 
        } 
 
        private ObservableCollection<ObjForTest> _children = new ObservableCollection<ObjForTest>(); 
        public ObservableCollection<ObjForTest> Children 
        { 
            get { return _children; } 
        } 
 
 
        public event PropertyChangedEventHandler PropertyChanged; 
    } 

ObjForTest是用來綁定的對象this._list.ItemsSource = root.Children;這句是用來綁定對象的children對象

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved