[我有废话要说]
PA的U。M界面的树也是我封装的,做这个功能的时候,我希望它可以像smart-gwt的treeGrid一样好用。
不过我不会C#,也第一次写ASP控件,还想让他像treeGrid……在这个难度上,我想再加点,把我的树写的通用又好维护,于是我决定好好设计,加入设计模式的思想:)
[正文——封个控件来画树]
需求:
领导说写个读取XML配置,让后封装成树,在界面上展示出来。
我是个画蛇添足的程序员,我想分两步完成,希望这个题目能两天就写完。
第一步:
从XML解析一棵树,放到tree中。并且考虑:如果XML格式变了、如果不从XML取数据库……要让我的代码尽量满足开闭原则。
第二步:
做一个渲染树的控件,将这个树丢到控件中,树就画出来了,可以多列。
开始干活:
我的树的设计
用户通过工厂类得到一个XML工厂。
XMLTreeReader工厂解析XML文件,把XML配置的指定解析自己的ITreeReader返回。(比如扁平或层级的表示树形的XML文件)
ITreeReader一拿到就可以开始干活了,ITreeReader解析xml的节点,把数据封装到树结构ITreeNode中。
这里需要注意的是:ITreeNode表示一个树的树根节点,有节点的属性,还有子节点。因此ITreeReader解析时候,需要创建子节点,也就是ITreeNode对象。而ITreeNode是接口,不能new出来,所以ITreeReader需要知道ITreeNode的实现类,于是我传入ITreeReader一个ITreeNode的实现类,反射来创建对象。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace com.Origin.Base.test.mywork.Tree
{
public interface ITreeReaderFactory
{
ITreeReader createTreeReader();
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace com.Origin.Base.test.mywork.Tree
{
public class XMLTreeRreaderFactory:ITreeReaderFactory
{
private string xmlPath {set;get; }
public XMLTreeRreaderFactory(string path)
{
xmlPath = path;
}
public ITreeReader createTreeReader()
{
//解析xmlPath路径下的xml文件,根据XML配置取得解析该XML对应的类,反射回去.
//这里把解析XML的一段省略了先,直接写死读到了xml配置的类:
string className = "com.Origin.Base.test.mywork.Tree.SimpleTreeReader";
Type type = Type.GetType(className);
Console.WriteLine(" 解析XML的类:" + type);
ITreeReader reader = (ITreeReader)type.Assembly.CreateInstance(className);
return reader;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace com.Origin.Base.test.mywork.Tree
{
public interface ITreeReader
{
ITreeNode createTree();
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace com.Origin.Base.test.mywork.Tree
{
public class SimpleTreeReader:ITreeReader
{
private static string DEFAULT_NODE_CLASS = "com.Origin.Base.test.mywork.Tree.MyTreeNode";
private string treeNodeClassName { set; get; }
public ITreeNode createTree()
{
ITreeNode treeNode = createNode();
//根据XML的结构,解析XML文件,封装到ITreeNode的对象中,返回
//这里不读取XML了,直接用假数据封装下。
treeNode.putAttribute("name"," 用户管理");
treeNode.putAttribute("url"," /userManage.html");
//创建子树
ITreeNode subNode = createNode();
subNode.putAttribute("name", "创建用户");
subNode.putAttribute("url", " /createUser.html");
treeNode.addSubNode(subNode);
return treeNode;
}
private ITreeNode createNode()
{
if (treeNodeClassName == null)
{
treeNodeClassName = DEFAULT_NODE_CLASS;
}
//再次用到反射
Type type = Type.GetType(treeNodeClassName);
ITreeNode treeNode = (ITreeNode)type.Assembly.CreateInstance(treeNodeClassName);
return treeNode;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace com.Origin.Base.test.mywork.Tree
{
public abstract class ITreeNode
{
protected IList<ITreeNode> subNodes { get; set; }
//设置当前节点的key-value对
public abstract void putAttribute(object key, object value);
//根据key得到对应的值
public abstract object getAttribute(object key);
//为当前节增加一个子节点,在它的节点的下一级节点的末尾增加
public abstract void addSubNode(ITreeNode node);
public abstract IList<ITreeNode> getSubNodes();
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Collections;
namespace com.Origin.Base.test.mywork.Tree
{
public class MyTreeNode : ITreeNode
{
private Hashtable attributes = new Hashtable();
//设置当前节点的key-value对
public override void putAttribute(object key, object value)
{
attributes.Add(key,value);
}
//根据key得到对应的值
public override object getAttribute(object key)
{
if (attributes.Contains(key))
{
return attributes[key];
}
else
{
return null;
}
}
//为当前节增加一个子节点,在它的节点的下一级节点的末尾增加
public override void addSubNode(ITreeNode node)
{
if (subNodes == null)
{
subNodes = new List<ITreeNode>();
}
subNodes.Add(node);
}
public override IList<ITreeNode> getSubNodes()
{
return subNodes;
}
}
}
看看client调用:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using com.Origin.Base.test.mywork.Tree;
namespace ConsoleApplication1
{
class Program
{
private ITreeReaderFactory factory = new XMLTreeRreaderFactory(@"D:\\menu.xml");
public ITreeNode fetchTreeNode()
{
ITreeNode root = null;
ITreeReader reader = factory.createTreeReader();
root = reader.createTree();
return root;
}
static void Main(string[] args)
{
Console.WriteLine("start...");
Program p = new Program();
ITreeNode root = p.fetchTreeNode();
string tab ="";
printTree(root, tab);
Console.ReadLine();
}
public static void printTree(ITreeNode node,string s)
{
s = " " + s;
Console.WriteLine(s + "NAME = " + node.getAttribute("name") + " url = " + node.getAttribute("url"));
IList<ITreeNode> subNodes = node.getSubNodes();
if (subNodes == null)
{
return;
}
for (int i = 0; i < subNodes.Count; i++)
{
printTree(subNodes[i],s);
}
}
}
}
输出:
分享到:
相关推荐
*5.6 C++处理字符串的方法——字符串类与字符串变量 5.6.1 字符串变量的定义和引用 5.6.2 字符串变量的运算 5.6.3 字符串数组 5.6.4 字符串运算举例 习题 第6章 指针 6.1 指针的概念 6.2 变量与指针 6.2.1 定义...
10.12 表格与树形的结合——Ext.ux.tree.ColumnTree 第11章 其他布局类简介 11.1 标准布局类 11.1.1 折叠布局——AccordionLayout 11.1.2 边框布局——BorderLayout 11.1.3 卡片式布局——CardLayout 11.1.4 ...
10.12 表格与树形的结合——Ext.ux.tree.ColumnTree 第11章 其他布局类简介 11.1 标准布局类 11.1.1 折叠布局——AccordionLayout 11.1.2 边框布局——BorderLayout 11.1.3 卡片式布局——CardLayout 11.1.4 ...
*5.6 C++处理字符串的方法——字符串类与字符串变量 5.6.1 字符串变量的定义和引用 5.6.2 字符串变量的运算 5.6.3 字符串数组 5.6.4 字符串运算举例 习题 第6章 指针 6.1 指针的概念 6.2 变量与指针 6.2.1 定义...
5个目标文件,演示Address EJB的实现,创建一个EJB测试客户端,得到名字上下文,查询jndi名,通过强制转型得到Home接口,getInitialContext()函数返回一个经过初始化的上下文,用client的getHome()函数调用Home接口...
5个目标文件,演示Address EJB的实现,创建一个EJB测试客户端,得到名字上下文,查询jndi名,通过强制转型得到Home接口,getInitialContext()函数返回一个经过初始化的上下文,用client的getHome()函数调用Home接口...