C#树状视图设计-显示树状结构的最佳方式?
我正在尝试使用TreeView来显示对象的树结构。我有一个由四种类型的对象组成的树:公司(根节点)、城市、商店和员工 该界面旨在添加/删除城市/商店/员工,因此树视图必须更新以反映任何更改 我想知道如何让TreeView显示树结构,并在树结构发生变化时接收更新 我认为Company对象应该有事件,比如Company.CityAdded和Company.CityRemoved,那么我在树视图中放置的任何包装都会响应这些事件吗?树视图建立后,每个城市/商店/员工将有一个节点。然后,每个节点都可以响应它在树中表示的节点的事件C#树状视图设计-显示树状结构的最佳方式?,c#,oop,treeview,C#,Oop,Treeview,我正在尝试使用TreeView来显示对象的树结构。我有一个由四种类型的对象组成的树:公司(根节点)、城市、商店和员工 该界面旨在添加/删除城市/商店/员工,因此树视图必须更新以反映任何更改 我想知道如何让TreeView显示树结构,并在树结构发生变化时接收更新 我认为Company对象应该有事件,比如Company.CityAdded和Company.CityRemoved,那么我在树视图中放置的任何包装都会响应这些事件吗?树视图建立后,每个城市/商店/员工将有一个节点。然后,每个节点都可以响应
这是正确的想法吗?或者有更好的方法吗?关于监听事件的概念,你说得对(这是一种标准的发布者/订阅者模式) 对于树视图的实际更新,我倾向于使用两种方法:
addorupdatetreeeitem
,和RemoveTreeItem
。add或update方法执行它所说的操作,查找树项(基于路径)并对其进行更新或添加。当然,如果在创建表单的线程以外的线程上更新模型,则需要使用Control.BeginInvoke()
封送调用
如果您在form_load或其他位置填充完整的树,这种方法可能会有点慢,因此对于初始填充,您可能有不同的方法,并使用我在这里描述的概念进行后续更新
我对ListView也这么做,下面是一个典型的例子。添加树项时的主要区别在于,您可能需要添加父节点才能添加所请求的节点,这使得它有点递归。试试看
private void AddOrUpdateListItem(DomainModelObject item)
{
ListViewItem li = lvwListView.Items[GetKey(item)];
if (li == null)
{
li = new ListViewItem
{
Name = GetKey(item),
Tag = item
};
li.SubItems.Add(new ListViewItem.ListViewSubItem());
li.SubItems.Add(new ListViewItem.ListViewSubItem());
li.SubItems.Add(new ListViewItem.ListViewSubItem());
li.ImageIndex = 0;
lvwListView.Items.Add(li);
}
li.Text = [Itemtext];
li.SubItems[1].Text = [Itemtext];
li.SubItems[2].Text = [Itemtext];
li.SubItems[3].Text = [Itemtext];
}
下面是一个如何实现BeginInvoke()
的示例:
public class MyForm : Form
{
...
void data_Changed(object sender, DataChangedEventArgs e)
{
if (this.InvokeRequired)
{
this.BeginInvoke(new EventHandler<DataChangedEventArgs>(data_Changed), sender, e);
return;
}
AddOrUpdateListItem(e.DataItem);
}
...
}
公共类MyForm:Form
{
...
无效数据\u已更改(对象发送方,DataChangedEventArgs e)
{
if(this.invokererequired)
{
this.BeginInvoke(新事件处理程序(数据已更改),发送方,e);
返回;
}
AddOrUpdateListItem(如数据项);
}
...
}
听起来你走对了路。我也做了类似的事情,我想分享一些建议:
- 业务对象订阅UI事件
- 命令更新用户界面
- 当UI更新时,业务对象也会更新
。。。您也可以用另一种方法(即命令更新业务对象树,从而相应地更新UI)。我只想补充一点,如果WPF是一个选项,那么使用Hierarchical数据绑定和observablecollections将变得非常简单。它基本上为您处理所有事件,并允许您与业务对象进行交互。发布/订阅更新模式的关键部分是如何包装事件触发时的操作信息 当表示“Store X”的对象更新为新名称,并触发事件以宣布此情况已发生时,哪个对象使用该事件 类似地,添加城市Y时,应通知哪个对象创建 一种常见的方法是使用某种大型uber manager类来处理整个过程——它订阅所有事件并执行所有操作 另一种方法是创建更简单的包装器/协调器对象,只处理拼图的一部分,这是我使用过的一种效果很好的方法。通常,我在这些类的名称后面加上“
Editor
”
因此,您可以有一个CityEditor
类,其构造函数同时接受City
对象和表示该对象的TreeNode
。CityEditor
将订阅City
对象和TreeNode
上的事件,并负责使用标题填充TreeNode
,并选择图标
当城市对象更新时,CityEditor
通过更新TreeNode
响应触发的事件。删除城市对象时,CityEditor
确保节点已从Treeview
中删除
当一个新的商店对象被添加到城市
中时,城市编辑器
可以创建一个商店编辑器
,以协调该级别的更新。类似地,当员工
被添加到商店
时,员工编辑器
的实例将处理树视图
+1的更新,以提及BeginInvoke()。但是,您可能需要修改示例来说明这一点。