[我有废话要说]
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);
}
}
}
}
输出:
分享到:
相关推荐
在这个“ASP.NET源码——无限级树形(三层开发)源码.zip”压缩包中,包含了一个使用ASP.NET实现的无限级树形结构的示例项目。下面我们将深入探讨这个项目的相关知识点。 首先,无限级树形结构在很多应用场景中非常...
Swing是Java的一个图形用户界面(GUI)工具包,它提供了丰富的组件,如按钮、文本框、菜单等,用于构建桌面应用程序。在这些实例中,你将接触到如何使用JFrame、JPanel、JButton、JLabel等Swing组件创建美观且功能...
在这个场景下,我们讨论的是一个自定义封装的级联菜单库——CascadingMenuViewLib。 1. **级联菜单原理**: 级联菜单,顾名思义,是指菜单项展开后会显示下一级的子菜单,这种效果就像瀑布一样逐级下落。在编程...
在这个项目中,MFC被用来实现文件系统的遍历和用户界面的构建,比如创建一个能够展示目录结构的树形视图。 描述中提到的“自动遍历目录”,指的是该小工具能够递归地读取指定目录及其子目录下的所有文件和子目录,...
在这个项目中,我们关注的是一个特定的应用——“学籍管理系统”,它使用了MFC(Microsoft Foundation Classes)框架,并在VC++ 6.0环境中进行编译。下面将详细阐述这个系统的设计和实现涉及的数据结构及编程知识。 ...
- **Factory 模式**:此模式提供了一个创建对象的接口,但允许子类决定实例化哪一个类。它将实例化推迟到子类。这种模式在实际项目中经常用于构建复杂的对象或者在运行时根据条件选择不同的对象创建策略。例如,在...
《zTree 3.518官方源码详解——打造高效可定制的树形界面组件》 zTree是一款广泛应用于Web开发中的JavaScript树形插件,它的最新版本为3.518。作为一款轻量级、高性能的开源组件,zTree以其强大的功能和灵活的配置...
4. 树形控件(Tree):用于展示层次结构的数据,可以展开、折叠节点。 5. 模态窗口(Window):浮动在页面上的全屏或半屏窗口,常用于展示独立的内容。 6. 菜单(Menu):创建下拉菜单或侧边栏菜单,支持多级结构。 ...
本示例代码着重于如何自定义一个结合了树形视图和列表视图功能的控件——TreeListView。这个控件允许用户以树形结构展示数据,同时每个节点下还可以有列表形式的子项,提供了一种灵活的数据展示方式。 树列表视图...
除了基本的 `GridPanel` 外,Ext JS 还提供了一个更为强大的表格组件——`EditorGridPanel`。这个组件允许用户直接在表格中进行数据编辑。下面是一个简单的使用 `EditorGridPanel` 的示例: ```javascript Ext....
EasyUI 提供了一系列预先封装的组件,如对话框、表单、菜单、树形结构等,帮助开发者轻松创建功能丰富的管理界面。 描述中提到的“漂亮的jquery easyui后台框架”,表明这个项目旨在提供一个易于使用的后台管理系统...
利用C++的数据结构如链表或树形结构,可以有效地存储和检索预订信息。同时,为了防止冲突,可能需要实现并发控制策略,如锁机制。 菜单管理模块涉及到菜品的添加、删除、更新,以及菜品价格、分类等信息的管理。C++...
*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 ...
6. **控件**:MFC提供了大量的控件类,如CEdit(编辑框)、CListBox(列表框)、CTreeCtrl(树形控件)等,用于构建用户界面。图书管理系统可能用到了这些控件来展示和选择图书信息。 7. **数据库支持**:MFC提供了...
`reselect-tree` 是一个专为前端设计的开源库,它专注于处理树形数据结构的选择操作,通过优化和封装,使得在复杂的前端应用中处理选择状态变得更加简单和高效。下面将详细探讨`reselect-tree`的相关知识点。 1. **...
*5.6 C++处理字符串的方法——字符串类与字符串变量 5.6.1 字符串变量的定义和引用 5.6.2 字符串变量的运算 5.6.3 字符串数组 5.6.4 字符串运算举例 习题 第6章 指针 6.1 指针的概念 6.2 变量与指针 6.2.1 定义...