从表到 TreeView…显示层次结构
谁还记得对象数据库? 曾经它们有望统治编程世界。 但就像许多被过度炒作的技术(Lisp、AI、ADA、虚拟现实)一样,它们注定要占据市场的一小部分利基领域。 关系数据库仍然是王者。 为什么? 因为关系数据库
谁还记得对象数据库? 曾经它们有望统治编程世界。 但就像许多被过度炒作的技术(Lisp、AI、ADA、虚拟现实)一样,它们注定要占据市场的一小部分利基领域。
关系数据库仍然是王者。 为什么? 因为关系数据库易于理解,而且效果很好……非常好。
尽管如此,很多时候层次数据存储在关系数据库中。 一个常见的例子是组织结构图。 这通常存储在一个 Employee 表中。 每个表行代表一个员工,包含一个 ID 字段和一个 ParentID(上司)字段。
这段代码展示了如何从层次表转换为树形视图。 这里没有什么复杂的,但需要一些技巧才能使其工作。
第一个技巧是按 ParentID 排序记录。 我们不能将节点插入到树中,直到其父节点在树中。 这意味着需要一种特殊情况,即首先插入树的根节点,因为它没有父节点。
这里是示例数据
// Create the DataTable and columns
DataTable ItemTable = new DataTable("MyTable");
ItemTable.Columns.Add("ID" , typeof(int ));
ItemTable.Columns.Add("ParentID", typeof(int ));
ItemTable.Columns.Add("Name" , typeof(String));
// add some test data
ItemTable.Rows.Add(new object[] { 0,-1, "Bill Gates" });
ItemTable.Rows.Add(new object[] { 1, 0, "Steve Ballmer" });
ItemTable.Rows.Add(new object[] { 3, 1, "Mary Smith" });
ItemTable.Rows.Add(new object[] { 2, 0, "Paul Allen" });
ItemTable.Rows.Add(new object[] { 4, 2, "Ahmed Jones" });
ItemTable.Rows.Add(new object[] { 5, 2, "Wing Lee" });
// Use the Select method to sort the rows by ParentID
DataRow[] SortedRows;
SortedRows = ItemTable.Select("", "ParentID");
第二个技巧是使用 XmlDocument。 最初,我尝试直接连接到树形视图,而无需中间数据对象。 但树形视图控件没有功能可以根据节点 ID 找到任意节点。 编写递归查找函数似乎需要很多工作,因此我们利用 XmlDocument 的 XPath 搜索功能来查找任意父节点。
// create an XmlDocument (with an XML declaration)
XmlDocument XDoc = new XmlDocument();
XmlDeclaration XDec = XDoc.CreateXmlDeclaration("1.0", null, null);
XDoc.AppendChild(XDec);
// iterate through the sorted data
// and build the XML document
foreach (DataRow Row in SortedRows)
{
// create an element node to insert
// note: Element names may not have spaces so use ID
// note: Element names may not start with a digit so add underscore
XmlElement NewNode = XDoc.CreateElement("_" + Row["ID"].ToString());
NewNode.SetAttribute("ID" , Row["ID"].ToString());
NewNode.SetAttribute("ParentID", Row["ParentID"].ToString());
NewNode.SetAttribute("FullName", Row["Name"].ToString());
// special case for top level node
if ((int)Row["ParentID"] == -1)
XDoc.AppendChild(NewNode); // root node
else
{
// use XPath to find the parent node in the tree
String SearchString;
SearchString = String.Format("//*[@ID=\"{0}\"] ", Row["ParentID"].ToString());
XmlNode Parent = XDoc.SelectSingleNode(SearchString);
if (Parent != null)
Parent.AppendChild(NewNode);
else
; // Handle Error: Employee with no boss
}
}
第三个技巧涉及文档中的一个错误。 树形视图(或菜单)无法绑定到 XmlDocument。 这样做会产生此错误:HierarchicalDataBoundControl only accepts data sources that implement IHierarchicalDataSource or IHierarchicalEnumerable。 解决方法是动态创建一个 XmlDataSource 控件,并将 XML 字符串分配给它。
// we cannot bind the TreeView directly to an XmlDocument
// so we must create an XmlDataSource and assign the XML text
XmlDataSource XDdataSource = new XmlDataSource();
XDdataSource.ID = DateTime.Now.Ticks.ToString(); // unique ID is required
XDdataSource.Data = XDoc.OuterXml;
// we want the full name displayed in the tree so
// do custom databindings
TreeNodeBinding Binding = new TreeNodeBinding();
Binding.TextField = "FullName";
Binding.ValueField = "ID";
TreeView1.DataBindings.Add(Binding);
// Finally! Hook that bad boy up!
TreeView1.DataSource = XDdataSource;
TreeView1.DataBind();
完成所有这些工作后,结果如下
希望对您有所帮助,
史蒂夫·韦伦斯。
附言:新年快乐 2008++;