1. 界面设计时在Tree View设计器或者代码中直接填充Tree View控件。
这种方式通过拖放控件的方式生成树,应用范围窄,是一种非编程方式;
2. 从XML文件中建立树形结构。
这种方式通过XML文件(串)生成树,从形式上来说,这种方式是比较直观的。因为XML本身就是一棵“树”,在.NET 平台下Tree View的自动生成代码中,Tree View的实际内容也是由XML表示的。此外,基于XML文件生成树对异构环境下的分布式应用(包括Web Service)具有重要意义。事实上,利用XML作为通用数据传递格式已得到普遍认可;
这种方式通过父子关系递归生成树,是最容易理解的一种编程实现方式。一般是自顶向下递归生成,得到广泛应用。
通过XML文件(串)生成树。这种方式实现的关键是构造出一个类似于Tree View的XML文档或字符串出来。其基本思想应该与传统的算法是相似的,只是在程序实现上稍微复杂一些。另外还要注意的是,有很多的第三方Tree View控件,他们所支持的XML文档的格式是不尽相同的,如表1所示。
Tree View控件 |
XML格式 |
By Microsoft |
<TREENODES> <treenode text="Modem" tag="xx"> <treenode text="Cable" tag="xx"> <treenode text="Broken" tag="xx"/> ... </treenode> ... </treenode> <treenode text="Monitor" tag="xx"> <treenode text="Fuzzy" tag="xx"> <treenode text="Driver" tag="xx"/> </treenode> </treenode> ... </TREENODES> |
By Infragistics(NetAdvantage) |
<?xml version='1.0' encoding='utf-8' standalone='yes'?> <Nodes> <Node> <Nodes> <Node> <Text>Child #1</Text> <Tag>hhee</Tag> <Nodes> <Node> <Text>Sub Child #1</Text> </Node> </Nodes> </Node> <Node> <Text>Child #2</Text> <Nodes> <Node> <Text>Sub Child #1</Text> <Nodes> <Node> <Text>Sub Sub Child #1</Text> </Node> </Nodes> </Node> </Nodes> </Node> </Nodes> </Node> </Nodes>
|
表1 XML文档格式对照表
这里不妨给出一个XML文档生成程序,XML节点的索引基于文档对象模型(DOM)。
/// <summary>
/// 将数据集转换为XML(根据父节点)
/// </summary>
/// <param name="dsSource">数据集</param>
/// <param name="strParentID">父节点ID</param>
/// <param name="iParentIndex">父节点索引(列号)</param>
/// <param name="iTagIndex">值索引(列号)</param>
/// <param name="iContentIndex">内容索引(列号)</param>
/// <returns>XML Document</returns>
public static XmlDocument DataSet2XML(DataSet dsSource,string strParentID,int iParentIndex,int iTagIndex,int iContentIndex)
{
System.Data.DataView dv = new DataView(dsSource.Tables[0]);
dv.RowFilter = dsSource.Tables[0].Columns[iParentIndex].ColumnName+"= '"+strParentID+"'";
XmlDocument objXmlDoc = new XmlDocument();
objXmlDoc.LoadXml("<?xml version ='1.0' ?><TREENODES></TREENODES>");
System.Xml.XmlNode objRootNode = objXmlDoc.SelectSingleNode("TREENODES");
AddXmlNodebyParent(dsSource,"",iParentIndex,iTagIndex,iContentIndex,objRootNode,objXmlDoc);
return objXmlDoc;
}
/// <summary>
/// 根据父节点增加xml节点
/// </summary>
/// <param name="dsSource">数据集</param>
/// <param name="strParentID">父节点ID</param>
/// <param name="iParentIndex">父节点索引(列号)</param>
/// <param name="iTagIndex">值索引(列号)</param>
/// <param name="iContentIndex">内容索引(列号)</param>
/// <param name="objNode">当前节点</param>
/// <param name="objXmlDoc">当前xml文档</param>
private static void AddXmlNodebyParent(DataSet dsSource,string strParentID,int iParentIndex,int iTagIndex,int iContentIndex,System.Xml.XmlNode objNode,XmlDocument objXmlDoc)
{
System.Data.DataView dv = new DataView(dsSource.Tables[0]);
dv.RowFilter = dsSource.Tables[0].Columns[iParentIndex].ColumnName+"= '"+strParentID+"'";//过滤出给定父节点的子节点
foreach(System.Data.DataRowView drow in dv)
{
//新节点
XmlElement objXmlElement = objXmlDoc.CreateElement("treenode");//创建一个<treenode>节点
objXmlElement.SetAttribute("text",drow[iContentIndex].ToString().Trim());//设置该节点text属性
objXmlElement.SetAttribute("tag",drow[iTagIndex].ToString().Trim());//设置该节点tag属性
objNode.AppendChild(objXmlElement);
//再次递归
AddXmlNodebyParent(dsSource,drow[iTagIndex].ToString().Trim(),iParentIndex,iTagIndex,iContentIndex,objXmlElement,objXmlDoc);
}
}
有了生成的XML文档,构造Tree View则是相当简单的,在NetAdvantage的Tree View控件中只需利用自带的Load方法加载一下XML文档即可。从软件体系结构的角度来看,用于显示的Tree View控件在生成过程中只用到后台或远程传递过来XML文档(串),无疑降低了耦合性。此外,一件有意义的工作就是设计XML到数据集的转换,得到具有本地结构的可操纵的数据集。
/// <summary>
/// 将数据集转换为XML(根据父节点)
/// </summary>
/// <param name="dsSource">数据集</param>
/// <param name="strParentID">父节点ID</param>
/// <param name="iParentIndex">父节点索引(列号)</param>
/// <param name="iTagIndex">值索引(列号)</param>
/// <param name="iContentIndex">内容索引(列号)</param>
/// <returns>XML Document</returns>
public static XmlDocument DataSet2XML(DataSet dsSource,string strParentID,int iParentIndex,int iTagIndex,int iContentIndex)
{
System.Data.DataView dv = new DataView(dsSource.Tables[0]);
dv.RowFilter = dsSource.Tables[0].Columns[iParentIndex].ColumnName+"= '"+strParentID+"'";
XmlDocument objXmlDoc = new XmlDocument();
objXmlDoc.LoadXml("<?xml version ='1.0' ?><TREENODES></TREENODES>");
System.Xml.XmlNode objRootNode = objXmlDoc.SelectSingleNode("TREENODES");
AddXmlNodebyParent(dsSource,"",iParentIndex,iTagIndex,iContentIndex,objRootNode,objXmlDoc);
return objXmlDoc;
}
/// <summary>
/// 根据父节点增加xml节点
/// </summary>
/// <param name="dsSource">数据集</param>
/// <param name="strParentID">父节点ID</param>
/// <param name="iParentIndex">父节点索引(列号)</param>
/// <param name="iTagIndex">值索引(列号)</param>
/// <param name="iContentIndex">内容索引(列号)</param>
/// <param name="objNode">当前节点</param>
/// <param name="objXmlDoc">当前xml文档</param>
private static void AddXmlNodebyParent(DataSet dsSource,string strParentID,int iParentIndex,int iTagIndex,int iContentIndex,System.Xml.XmlNode objNode,XmlDocument objXmlDoc)
{
System.Data.DataView dv = new DataView(dsSource.Tables[0]);
dv.RowFilter = dsSource.Tables[0].Columns[iParentIndex].ColumnName+"= '"+strParentID+"'";//过滤出给定父节点的子节点
foreach(System.Data.DataRowView drow in dv)
{
//新节点
XmlElement objXmlElement = objXmlDoc.CreateElement("treenode");//创建一个<treenode>节点
objXmlElement.SetAttribute("text",drow[iContentIndex].ToString().Trim());//设置该节点text属性
objXmlElement.SetAttribute("tag",drow[iTagIndex].ToString().Trim());//设置该节点tag属性
objNode.AppendChild(objXmlElement);
//再次递归
AddXmlNodebyParent(dsSource,drow[iTagIndex].ToString().Trim(),iParentIndex,iTagIndex,iContentIndex,objXmlElement,objXmlDoc);
}
}
有了生成的XML文档,构造Tree View则是相当简单的,在NetAdvantage的Tree View控件中只需利用自带的Load方法加载一下XML文档即可。从软件体系结构的角度来看,用于显示的Tree View控件在生成过程中只用到后台或远程传递过来XML文档(串),无疑降低了耦合性。此外,一件有意义的工作就是设计XML到数据集的转换,得到具有本地结构的可操纵的数据集。
调用示例:
string strXml = "<?xml version='1.0' encoding='utf-8' standalone='yes'?><Nodes><Node><Nodes><Node><Text>Child #1</Text><Tag>hhee</Tag><Nodes><Node><Text>Sub Child #1</Text></Node></Nodes></Node><Node><Text>Child #2</Text><Nodes><Node><Text>Sub Child #1</Text><Nodes><Node><Text>Sub Sub Child #1</Text></Node></Nodes></Node></Nodes></Node></Nodes></Node></Nodes>";
this.UltraWebTree1.ReadXmlString(strXml,true,false);
(to be continued)