windows窗体
TreeView
不知道如何绑定到
IHierarchyData
实例,这并不奇怪,因为
伊赫拉奇达
和相关的接口是供web控件使用的(特别是站点地图)。
然而,构建自己的数据绑定类并不难。这似乎是一个有趣的问题,所以我把一个只是为了好玩。我带你去看看内部运作。
首先,创建一个基本组件类。Visual Studio将以如下代码开始:
public partial class TreeViewHierarchyBinding : Component
{
public TreeViewHierarchyBinding()
{
InitializeComponent();
}
public TreeViewHierarchyBinding(IContainer container)
{
container.Add(this);
InitializeComponent();
}
}
这个组件需要的一个明显的“状态”是
TreeNode
对其
伊赫拉奇达
. 现在我们可以把它扔进
树冠
的
Tag
属性,但我们的目标是使此组件尽可能无创,并跟踪其自身状态。因此,我们将使用词典。将此字段添加到类:
private Dictionary<TreeNode, IHierarchyData> nodeDictionary = new
Dictionary<TreeNode, IHierarchyData>();
现在,至少,这个组件需要知道如何填充特定的父组件
树冠
A的
树视图
类的相应绑定
伊赫拉奇达
,下面我们来编写代码:
private void PopulateChildNodes(TreeNodeCollection parentCollection,
IHierarchicalEnumerable children)
{
parentCollection.Clear();
foreach (object child in children)
{
IHierarchyData childData = children.GetHierarchyData(child);
TreeNode childNode = new TreeNode(childData.ToString());
if (childData.HasChildren)
{
childNode.Nodes.Add("Dummy"); // Make expandable
}
nodeDictionary.Add(childNode, childData);
parentCollection.Add(childNode);
}
}
private void UpdateRootNodes(TreeView tv, IHierarchyData hierarchyData)
{
if (tv == null)
{
return;
}
tv.Nodes.Clear();
if (hierarchyData != null)
{
IHierarchicalEnumerable roots = hierarchyData.GetChildren();
PopulateChildNodes(tv.Nodes, roots);
}
}
这部分应该很简单。第一种方法只是填充
TreeNodeCollection
(即
Nodes
财产
树冠
)从
伊赫拉奇达
实例,使用
IHierarchyEnumerable
接口。这种方法唯一真正有趣的地方是:
-
当
伊赫拉奇达
实例有子实例;这使“+”在树状视图中可见,否则我们将无法展开得更深;并且
-
使用
伊赫拉奇达
与之匹配的实例。
第二种方法更简单,它执行初始的“绑定工作”,替换
根
我们的顶级
伊赫拉奇达
实例。
我们的组件需要做的下一件事是从
树视图
执行延迟加载。下面是执行此操作的代码:
private void RegisterEvents(TreeView tv)
{
tv.BeforeExpand += TreeViewBeforeExpand;
}
private void UnregisterEvents(TreeView tv)
{
tv.BeforeExpand -= TreeViewBeforeExpand;
}
private void TreeViewBeforeExpand(object sender, TreeViewCancelEventArgs e)
{
if (e.Node.Checked)
{
return;
}
IHierarchyData hierarchyData;
if (nodeDictionary.TryGetValue(e.Node, out hierarchyData))
{
PopulateChildNodes(e.Node.Nodes, hierarchyData.GetChildren());
e.Node.Checked = true;
}
}
前两个方法应该是自解释的,第三个方法是实际的延迟加载代码。我们有点作弊,用
TreeNode.Checked
属性来描述是否已加载子节点,以便我们不进行任何不必要的重新加载。当我实现延迟加载的树时,我总是这样做,因为根据我的经验,我几乎从不使用
Treenode.已检查
财产。但是,如果确实需要将此属性用于其他用途,则可以使用其他属性(如
标签
,创建另一个字典以保存展开的状态,或修改现有字典以保存复合类(包含
伊赫拉奇达
以及
Expanded
财产)。我暂时保持简单。
如果之前在树中实现了延迟加载,那么剩下的应该已经有意义了,所以让我们跳过前面的步骤。现在唯一要做的就是实现一些设计器/用户属性,这些属性将真正连接树和数据:
private IHierarchyData dataSource;
private TreeView treeView;
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public IHierarchyData DataSource
{
get { return dataSource; }
set
{
if (value != dataSource)
{
dataSource = value;
nodeDictionary.Clear();
UpdateRootNodes(treeView, value);
}
}
}
[Category("Behavior")]
[DefaultValue(null)]
[Description("Specifies the TreeView that the hierarchy should be bound to.")]
public TreeView TreeView
{
get { return treeView; }
set
{
if (value != treeView)
{
if (treeView != null)
{
UnregisterEvents(treeView);
}
treeView = value;
nodeDictionary.Clear();
RegisterEvents(value);
UpdateRootNodes(treeView, dataSource);
}
}
}
轻松点。我们有一个
DataSource
接受根的属性
伊赫拉奇达
和A
树视图
可以从设计器访问的属性。再说一次,简单的事情,当
数据来源
属性已更新,我们只需重置查找并重新填充根。当
树视图
属性更新后,我们需要做更多的工作,注册事件,确保从旧树视图中注销事件,并在数据源更改时执行所有相同的操作。
这就是它的全部!打开windows窗体设计器,删除
树视图
,然后放下
TreeViewHierarchyBinding
并设置其
树视图
属性设置为刚才删除的树视图。最后,在你的代码中的某个地方(即
Form_Load
事件),给它一个数据源:
private void Form1_Load(object sender, EventArgs e)
{
DirectoryInfo dir = new DirectoryInfo("C:\\");
treeViewHierarchyBinding1.DataSource = new FileSystemHierarchyData(dir);
}
(注意-这使用了示例
FileSystemHierarchyData
上面写着
MSDN page for IHierarchyData
. 这个例子不太可靠,它没有检查
UnauthorizedAccessException
或者其他什么,但这足以证明这一点)。
就这样。运行你的应用程序并观看它绑定。现在可以重用
树状缠绕
组件在任何地方-只要把它放到表单上,给它分配一个
树视图
,然后给它一个
伊赫拉奇达
实例作为数据源。
我已经把
complete code on PasteBin
如果你想要复制粘贴版本。
玩得高兴!