WPF 的功能非常强大,很多控件都是原生的,但是要使用 TreeView+DataGrid 的组合,就需要我们自己去封装实现。
我们需要的效果如图所示:


这两个图都是第三方控件自带的,并且都是收费使用。现在我们就用原生的控件进行封装一个。
功能如上图所示,目前基本上把常用的样式都实现了。
首先说明一下,实现上面的效果,有 3 种方法:
- 技术的选择是 TreeView。
- 技术的选择是 DataGrid。
- 技术的选择是 ListView(也就是本文的演示)。
本文演示的是 ListView 的实现。
1. 首先建立一个 WPF 程序
2. 封装 TreeList.cs
namespace ListView.TreeDataGrid
{
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
public class TreeList : ListView
{
#region Properties
/// <summary>
/// Internal collection of rows representing visible nodes, actually displayed in the ListView
/// </summary>
ObservableCollectionAdv<TreeNode> Rows
{
; ;
}
ITreeModel _model;
ITreeModel Model
{
{ _model; }
{
(_model != )
{
_model = ;
_root.Children.Clear();
Rows.Clear();
CreateChildrenNodes(_root);
}
}
}
TreeNode _root;
TreeNode Root
{
{ _root; }
}
{
{ Root.Nodes; }
}
TreeNode PendingFocusNode
{
; ;
}
{
{
SelectedItems.Cast<TreeNode>().ToArray();
}
}
TreeNode SelectedNode
{
{
(SelectedItems.Count > )
SelectedItems[] TreeNode;
;
}
}
{
Rows = ObservableCollectionAdv<TreeNode>();
_root = TreeNode(, );
_root.IsExpanded = ;
ItemsSource = Rows;
ItemContainerGenerator.StatusChanged += ItemContainerGeneratorStatusChanged;
}
{
(ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated && PendingFocusNode != )
{
item = ItemContainerGenerator.ContainerFromItem(PendingFocusNode) TreeListItem;
(item != )
item.Focus();
PendingFocusNode = ;
}
}
{
TreeListItem();
}
{
item TreeListItem;
}
{
ti = element TreeListItem;
node = item TreeNode;
(ti != && node != )
{
ti.Node = item TreeNode;
.PrepareContainerForItemOverride(element, node.Tag);
}
}
{
()
{
(!node.IsExpandedOnce)
{
node.IsExpandedOnce = ;
node.AssignIsExpanded();
CreateChildrenNodes(node);
}
{
node.AssignIsExpanded();
CreateChildrenRows(node);
}
}
{
DropChildrenRows(node, );
node.AssignIsExpanded();
}
}
{
children = GetChildren(node);
(children != )
{
rowIndex = Rows.IndexOf(node);
node.ChildrenSource = children INotifyCollectionChanged;
( obj children)
{
TreeNode child = TreeNode(, obj);
child.HasChildren = HasChildren(child);
node.Children.Add(child);
}
Rows.InsertRange(rowIndex + , node.Children.ToArray());
}
}
{
index = Rows.IndexOf(node);
(index >= || node == _root)
{
nodes = node.AllVisibleChildren.ToArray();
Rows.InsertRange(index + , nodes);
}
}
{
start = Rows.IndexOf(node);
(start >= || node == _root)
{
count = node.VisibleChildrenCount;
(removeParent)
count++;
start++;
Rows.RemoveRange(start, count);
}
}
{
(Model != )
Model.GetChildren(parent.Tag);
;
}
{
(parent == Root)
;
(Model != )
Model.HasChildren(parent.Tag);
;
}
{
TreeNode node = TreeNode(, tag);
(index >= && index < parent.Children.Count)
parent.Children.Insert(index, node);
{
index = parent.Children.Count;
parent.Children.Add(node);
}
Rows.Insert(rowIndex + index + , node);
}
}
}



