TreeView

TreeView 控件时最重要的Windows控件之一,它被集成到Windows 资源管理器乃至 .Net 帮助文档库等各种元素中。WPF中实现的TreeView 控件更是令人印象深刻,因为它完全支持数据绑定。

TreeView 控件在本质上是驻留TreeViewItem 对象的特殊ItemsControl 控件。但与ListViewItem 对象不同,TreeViewItem 对象不是内容控件。相反,每个TreeViewItem 对象都是单独的ItemsControl 控件,可以包含更多TreeViewItem 对象。通过这一灵活性,可以创建更深层次的数据显示。

使用标记声明的TreeView :


    
        
        
        
    
    
        
        
        
    

可以看到使用起来非常简单,只有几个Header字段,TreeViewItem可以多层次嵌套。

使用数据绑定


    
        
            
            
                
                    
                    
                        
                            
                        
                    
                
            
        
    

这里需要逐层写模板,每层只有一个TextBlock用于显示Header字段。

实际上,现在有两个模板,每个模板用于树控件中的每个层次。第二个模板使用从第一个模板中选择的项作为其数据源。

尽管这个标记工作的很好,单分解每个数据模板并通过数据类型(而不是通过位置)将模板应用到数据对象的情况更加普遍。


    
        
            
        
        
            
        
        
            
        
    
    
        
            
        
    

TreeView 控件经常用于包含大量数据,这是因为TreeView 控件的显示是能够折叠的。即使用户从顶部滚动到底部,也不需要显示全部信息。完全可以在TreeView 控件中省略不显示的信息,以便降低开销。甚至更好的是,当展开每个TreeViewItem 对象时会引发 Expanded 事件,并且当关闭时会引发 Collapsed 事件。可通过处理这两个事件即时填充丢失的节点或丢弃不需要的节点。这种技术被称为即时创建节点。


    
    private void BuildTree()
    {
        treeFileSystem.Items.Clear();

        foreach (DriveInfo drive in DriveInfo.GetDrives())
        {
            TreeViewItem item = new TreeViewItem();
            item.Tag = drive;
            item.Header = drive.ToString();
            item.Items.Add("*");
            treeFileSystem.Items.Add(item);
        }
    }
    private void treeFileSystem_Expanded(object sender, RoutedEventArgs e)
    {
        TreeViewItem item = (TreeViewItem)e.OriginalSource;
        item.Items.Clear();
        DirectoryInfo dir;
        if (item.Tag is DriveInfo)
        {
            DriveInfo drive = (DriveInfo)item.Tag;
            dir = drive.RootDirectory;
        }
        else
        {
            dir = (DirectoryInfo)item.Tag;
        }

        try
        {
            foreach (DirectoryInfo subDir in dir.GetDirectories())
            {
                TreeViewItem newItem = new TreeViewItem();
                newItem.Tag = subDir;
                newItem.Header = subDir.ToString();
                newItem.Items.Add("*");
                item.Items.Add(newItem);
            }
        }
        catch
        {
            // An exception could be thrown in this code if you don't
            // have sufficient security permissions for a file or directory.
            // You can catch and then ignore this exception.
        }
    }

完整的测试代码:

MainWindow.xaml


    
        
            
        
        
            
        
        
            
        
    
    
        
            
            
        
        
            
            
            
        
        
            
                
                    
                    
                    
                
                
                    
                    
                    
                
            
        
        
            
                
                    
                        
                        
                            
                                
                                
                                    
                                        
                                    
                                
                            
                        
                    
                
            
        

        
            
        
        
            
        

        
            
        

        
            
        
    

MainWindow.xaml.cs

using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System;
using System.Windows;
using System.Collections.ObjectModel;
using System.Windows.Controls;
using System.IO;

namespace TestTreeView;


public class ViewModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler? PropertyChanged;
    protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
    protected virtual bool SetProperty(ref T member, T value, [CallerMemberName] string? propertyName = null)
    {
        if (EqualityComparer.Default.Equals(member, value))
        {
            return false;
        }
        member = value;
        OnPropertyChanged(propertyName);
        return true;
    }
}
public class Order : ViewModelBase
{
    private decimal price = 0;
    public decimal Price { get => price; set => SetProperty(ref price, value); }
    private int volume = 0;
    public int Volume { get => volume; set => SetProperty(ref volume, value); }

    private DateTime orderDate = DateTime.Now;
    public DateTime OrderDate { get => orderDate; set => SetProperty(ref orderDate, value); }

    private string image = string.Empty;
    public string Image { get => image; set => SetProperty(ref image, value); }
}
public class Account : ViewModelBase
{
    private string accountID = string.Empty;
    public string AccountID { get => accountID; set => SetProperty(ref accountID, value); }
    private ObservableCollection orders = new ObservableCollection();
    public ObservableCollection Orders { get => orders; set => SetProperty(ref orders, value); }
}
public class AccountGroup : ViewModelBase
{
    private string groupID = string.Empty;
    public string GroupID { get => groupID; set => SetProperty(ref groupID, value);}
    private ObservableCollection accounts = new ObservableCollection();
    public ObservableCollection Accounts { get => accounts; set => SetProperty(ref accounts, value);}
}


public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        myGrid.DataContext = this;

        InitAccountGroup();

        BuildTree();
    }

    public void InitAccounts()
    {
        Order order1 = new Order();
        Order order2 = new Order();
        Order order3 = new Order();
        Order order4 = new Order();

        order1.Price = 100;
        order1.Volume = 10;
        order1.Image = "image1.gif";

        order2.Price = 1000;
        order2.Volume = 100;
        order2.Image = "image2.gif";

        order3.Price = 10000;
        order3.Volume = 1000;
        order3.Image = "image3.gif";

        order4.Price = 100000;
        order4.Volume = 10000;
        order4.Image = "image4.gif";

        Account account1 = new Account();
        Account account2 = new Account();

        account1.AccountID = "Account1";
        account1.Orders.Add(order1);
        account1.Orders.Add(order2);

        account2.AccountID = "Account2";
        account2.Orders.Add(order3);
        account2.Orders.Add(order4);

        Accounts.Add(account1);
        Accounts.Add(account2);
    }
    public void InitAccountGroup()
    {
        InitAccounts();

        AccountGroup accountGroup1 = new AccountGroup();
        AccountGroup accountGroup2 = new AccountGroup();

        accountGroup1.GroupID = "Group1";
        accountGroup1.Accounts = Accounts;

        accountGroup2.GroupID = "Group2";
        accountGroup2.Accounts = Accounts;
        
        AccountGroups.Add(accountGroup1);
        AccountGroups.Add(accountGroup2);
    }

    public ObservableCollection Accounts { get; set; } = new ObservableCollection();

    public ObservableCollection AccountGroups { get; set; } = new ObservableCollection();

    private void BuildTree()
    {
        treeFileSystem.Items.Clear();

        foreach (DriveInfo drive in DriveInfo.GetDrives())
        {
            TreeViewItem item = new TreeViewItem();
            item.Tag = drive;
            item.Header = drive.ToString();
            item.Items.Add("*");
            treeFileSystem.Items.Add(item);
        }
    }
    private void treeFileSystem_Expanded(object sender, RoutedEventArgs e)
    {
        TreeViewItem item = (TreeViewItem)e.OriginalSource;
        item.Items.Clear();
        DirectoryInfo dir;
        if (item.Tag is DriveInfo)
        {
            DriveInfo drive = (DriveInfo)item.Tag;
            dir = drive.RootDirectory;
        }
        else
        {
            dir = (DirectoryInfo)item.Tag;
        }

        try
        {
            foreach (DirectoryInfo subDir in dir.GetDirectories())
            {
                TreeViewItem newItem = new TreeViewItem();
                newItem.Tag = subDir;
                newItem.Header = subDir.ToString();
                newItem.Items.Add("*");
                item.Items.Add(newItem);
            }
        }
        catch
        {
            // An exception could be thrown in this code if you don't
            // have sufficient security permissions for a file or directory.
            // You can catch and then ignore this exception.
        }
    }
}

你可能感兴趣的:(紫云的程序人生,C#,WPF,wpf,TreeView)