本文内容
- 概述
- 演示在程序集中自定义 TreePanel 控件
- 运行结果
概述
- 博文 Ext.Net_在 Web 应用程序中自定义 TreePanel 控件。演示如何用 Ext.Net 在 Web 应用程序中自定义 TreePanel 控件。自定义的 TreePanel 控件由两个文件、三部分组成:控件的类文件和外部脚本文件。其中,控件类文件是一个分部类,分别实现控件的 UI 代码和逻辑代码。UI 代码负责创建控件标记;逻辑代码创建控件的客户端事件和服务器端事件。外部脚本文件用于在客户端操作控件。
- 博文 Ext.Net_在程序集中自定义 TreePanel 控件。Ext.Net_在 Web 应用程序中自定义 TreePanel 控件演示的类和脚本文件都在 Web 应用程序中。而该演示类和脚本都在程序集中,并把脚本文件作为程序集的嵌入资源,在 Web 应用程序中,通过 WebResource 方式引入。
本文的演示与 Ext.Net_在程序集中自定义 TreePanel 控件 的唯一区别是,后者创建树形结构的数据源是固定的,而前者是通过反射类中的方法动态获得。如下所示:
<MyExtNet:TreePanel ID="TreePanel1" runat="server" CustomFullName="MyExtNet.MyControl.DataBase"
CustomMethod="GetData" CustomParams="-1" Width="200px" Height="300px" AutoScroll="true"
Lines="false">
</MyExtNet:TreePanel>
其中,
- TreePanel1 控件为自定义控件;
- CustomFullName 属性是类全名,即程序集命名空间+类名;
- CustomMethod 属性是类的方法;
- CustomParams 属性是类中方法的参数。
演示在程序集中自定义 TreePanel 控件
解决方案结构
自定义 TreePanel UI
using System;
using System.Collections.Generic;
using System.ComponentModel;
using Ext.Net;
using System.Reflection;
using System.Data;
namespace MyExtNet.MyControl
{
public partial class TreePanel : Ext.Net.TreePanel
{
private DataTable dataSource;
[DefaultValue("")]
[Description("自定义程序集)")]
public string CustomFullName
{
get
{
return (string)this.ViewState["CustomFullName"] ?? "";
}
set { this.ViewState["CustomFullName"] = value; }
}
[DefaultValue("")]
[Description("自定义方法名")]
public string CustomMethod
{
get
{
return (string)this.ViewState["CustomMethod"] ?? "";
}
set { this.ViewState["CustomMethod"] = value; }
}
[DefaultValue("-1")]
[Description("自定义方法的参数列表,逗号分隔")]
public string CustomParams
{
get
{
return (string)this.ViewState["CustomParams"] ?? "";
}
set { this.ViewState["CustomParams"] = value; }
}
/// <summary>
///
/// </summary>
[DefaultValue(true)]
[Description("节点前是否有勾选框")]
public bool CustomHasCheck
{
get
{
object obj = this.ViewState["CustomHasCheck"];
return (obj == null) ? false : (bool)obj;
}
set { this.ViewState["CustomHasCheck"] = value; }
}
public TreePanel()
{
this.RootVisible = false;
this.SelectionModel.Add(new Ext.Net.DefaultSelectionModel());
}
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
this.GetDataSource();
this.BuildTree();
this.InitLogic();
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
string webResource = this.ResourceManager.GetWebResourceUrl(this.GetType(), "MyExtNet.MyControl.Resources.myTreePanel.js");
this.ResourceManager.RegisterClientScriptInclude(string.Format("{0}_Script", MyExtNet.MyControl.TreePanel.SCOPE), webResource);
}
/// <summary>
/// 创建树形结构 TreePanel
/// </summary>
protected void BuildTree()
{
if (this.dataSource == null)
{
throw new NullReferenceException();
}
TreeNode topNode = new TreeNode();
topNode.NodeID = "0";
topNode.Text = "Root";
DataRow[] items = dataSource.Select("ParentID=" + this.CustomParams);
if (items != null && items.Length > 0)
{
DataSet ds = new DataSet();
ds.Merge(items);
DataTable SourseTable = ds.Tables[0];
for (int i = 0; i < SourseTable.Rows.Count; i++)
{
TreeNode node = new TreeNode();
node.NodeID = SourseTable.Rows[i]["ID"].ToString();
node.Text = SourseTable.Rows[i]["NAME"].ToString();
DataRow[] isChildNode = dataSource.Select("parentid=" + SourseTable.Rows[i]["ID"].ToString());
// 父节点与子节点图标
if (isChildNode.Length > 0) node.Icon = Icon.FolderGo;
else node.Icon = Icon.Table;
// 父节点与子节点标记
if (isChildNode.Length <= 0) node.Leaf = true;
else node.Leaf = false;
if (!CustomHasCheck)
{
node.Checked = Ext.Net.ThreeStateBool.False;
}
topNode.Nodes.Add(node);
BuildTree(node, SourseTable.Rows[i]["ID"].ToString());
}
}
this.Root.Add(topNode);
}
/// <summary>
///
/// </summary>
/// <param name="TrNode"></param>
/// <param name="parentID"></param>
private void BuildTree(TreeNode TrNode, string parentID)
{
DataRow[] items = dataSource.Select("ParentID=" + parentID);
if (items != null && items.Length > 0)
{
DataSet ds = new DataSet();
ds.Merge(items);
DataTable dt = ds.Tables[0];
for (int i = 0; i < dt.Rows.Count; i++)
{
TreeNode node = new TreeNode();
node.NodeID = dt.Rows[i]["ID"].ToString();
node.Text = dt.Rows[i]["NAME"].ToString();
DataRow[] isChildNode = dataSource.Select("parentid=" + dt.Rows[i]["ID"].ToString());
// 父节点与子节点图标
if (isChildNode.Length > 0) node.Icon = Icon.FolderGo;
else node.Icon = Icon.Table;
// 父节点与子节点标记
if (isChildNode.Length <= 0) node.Leaf = true;
else node.Leaf = false;
if (!CustomHasCheck)
{
node.Checked = Ext.Net.ThreeStateBool.False;
}
TrNode.Nodes.Add(node);
BuildTree(node, dt.Rows[i]["ID"].ToString());
}
}
}
/// <summary>
/// 获得数据
/// </summary>
protected void GetDataSource()
{
if (this.CustomFullName.Length > 0 && this.CustomMethod.Length > 0)
{
Type type = null;
type = this.CustomFullName.Substring(0, this.CustomFullName.LastIndexOf('.')) == this.GetType().ToString().Substring(0, this.GetType().ToString().LastIndexOf('.')) ?
Type.GetType(this.CustomFullName) : Assembly.Load(CustomFullName.Substring(0, this.CustomFullName.LastIndexOf('.'))).GetType(this.CustomFullName);
MethodInfo method = type.GetMethod(this.CustomMethod);
object value = null;
if (method.IsStatic)
value = method.Invoke(null, null);
else
{
ConstructorInfo dataBaseC = type.GetConstructor(Type.EmptyTypes);
object dataBase = dataBaseC.Invoke(new object[] { });
value = method.Invoke(dataBase, null);
}
this.dataSource = (DataTable)value;
}
}
}
}
自定义 TreePanel Logic
using System;
using Ext.Net.Utilities;
using Ext.Net;
namespace MyExtNet.MyControl
{
[DirectMethodProxyID(IDMode = DirectMethodProxyIDMode.None)]
public partial class TreePanel
{
public const string SCOPE = "MyExtNet.MyControl.TreePanel";
private void InitLogic()
{
this.Listeners.Render.Fn = TreePanel.SCOPE + ".init";
this.Listeners.Render.Scope = TreePanel.SCOPE;
this.Listeners.CheckChange.Handler = TreePanel.SCOPE + ".SelectParentChildNodes(node,checked);";
Ext.Net.Button button = new Ext.Net.Button();
button.ID = "btnGet";
button.Text = "获得勾选";
button.Listeners.Click.Handler = TreePanel.SCOPE + ".getSelectedNode('" + this.ClientID + "')";
this.Buttons.Add(button);
button = new Ext.Net.Button();
button.ID = "btnClear";
button.Text = "清除勾选";
button.Listeners.Click.Handler = TreePanel.SCOPE + ".clearSelectedNode('" + this.ClientID + "')";
this.Buttons.Add(button);
}
}
}
自定义数据源,数据文件 MyData.xml 以及相应的类,包括非静态类 DataBase 和静态类 DataBaseStatic
- 数据文件 MyData.xml
<?xml version="1.0" standalone="yes"?>
<data>
<datas>
<ID>208</ID>
<CLASSID>195</CLASSID>
<PARENTID>-1</PARENTID>
<CODE>-1</CODE>
<NAME>河北省</NAME>
<CANCUSTOM>0</CANCUSTOM>
<INSERTEDDATE>2011-10-25T10:36:16+08:00</INSERTEDDATE>
<VALUE>130000</VALUE>
<CHILDSTART>0.01</CHILDSTART>
<CHILDEND>0.01</CHILDEND>
</datas>
<datas>
<ID>213</ID>
<CLASSID>195</CLASSID>
<PARENTID>208</PARENTID>
<CODE>-1</CODE>
<NAME>邢台市</NAME>
<CANCUSTOM>0</CANCUSTOM>
<INSERTEDDATE>2011-10-25T10:38:23+08:00</INSERTEDDATE>
<VALUE>130500</VALUE>
<CHILDSTART>0.01</CHILDSTART>
<CHILDEND>0.01</CHILDEND>
</datas>
<datas>
<ID>210</ID>
<CLASSID>195</CLASSID>
<PARENTID>208</PARENTID>
<CODE>-1</CODE>
<NAME>唐山市</NAME>
<CANCUSTOM>0</CANCUSTOM>
<INSERTEDDATE>2011-10-25T10:37:09+08:00</INSERTEDDATE>
<VALUE>130200</VALUE>
<CHILDSTART>0.01</CHILDSTART>
<CHILDEND>0.01</CHILDEND>
</datas>
……
</data>
- 非静态类 DataBase
using System;
using System.Data;
namespace MyExtNet.MyControl
{
public class DataBase
{
public DataTable GetData()
{
DataSet ds = new DataSet();
ds.ReadXml(AppDomain.CurrentDomain.BaseDirectory + "MyData.xml");
DataTable dt = ds.Tables[0];
return dt;
}
}
}
- 静态类 DataBaseStatic
using System;
using System.Data;
namespace MyExtNet.MyControl
{
public static class DataBaseStatic
{
public static DataTable GetData()
{
DataSet ds = new DataSet();
ds.ReadXml(AppDomain.CurrentDomain.BaseDirectory + "MyData.xml");
DataTable dt = ds.Tables[0];
return dt;
}
}
}
自定义脚本 myTreePanel.js
Ext.ns("MyExtNet.MyControl");
MyExtNet.MyControl.TreePanel = {
tr: null,
init: function(tree) {
this.tr = tree;
},
SelectParentChildNodes: function(node, state) {
var tree = node.getOwnerTree();
tree.suspendEvents();
if (node.parentNode != null) {
// 勾选该节点所有子节点
node.cascade(function(node) {
node.attributes.checked = state;
node.ui.toggleCheck(state);
return true;
});
// 勾选该节点父节点
var pNode = node.parentNode;
while (pNode.id != '0' && pNode != null) {
if (state) { //如果选中状态无所谓
pNode.ui.toggleCheck(state);
pNode.attributes.checked = state;
pNode = pNode.parentNode;
}
else { //如果未选中状态,需要查看该节点是否所有子节点都未选中
var chk = false;
pNode.eachChild(function(child) {
if (child.attributes.checked || child.getUI().isChecked())
chk = true;
});
pNode.ui.toggleCheck(chk);
pNode.attributes.checked = chk;
pNode = pNode.parentNode;
}
}
}
tree.resumeEvents();
},
getSelectedNode: function(treeId) {
var tree = Ext.getCmp(treeId);
var msg = [];
var selNodes = tree.getChecked();
Ext.each(selNodes, function(node) {
msg.push(node.text);
});
Ext.Msg.show({
title: "勾选节点",
msg: msg.join(','),
icon: Ext.Msg.INFO,
minWidth: 200,
buttons: Ext.Msg.OK
});
},
clearSelectedNode: function(treeId) {
var tree = Ext.getCmp(treeId);
tree.clearChecked();
}
};
创建页面
<%@ Page Language="C#" %>
<%@ Register Assembly="Ext.Net" Namespace="Ext.Net" TagPrefix="ext" %>
<%@ Register Assembly="MyExtNet.MyControl" Namespace="MyExtNet.MyControl" TagPrefix="MyExtNet" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<ext:ResourcePlaceHolder ID="ResourcePlaceHolder1" runat="server" Mode="Script" />
</head>
<body>
<form id="form1" runat="server">
<ext:ResourceManager ID="ResourceManager1" runat="server">
</ext:ResourceManager>
<div style="float: left">
<MyExtNet:TreePanel ID="TreePanel1" runat="server" CustomFullName="MyExtNet.MyControl.DataBase"
CustomMethod="GetData" CustomParams="-1" Width="200px" Height="300px" AutoScroll="true"
Lines="false">
</MyExtNet:TreePanel>
</div>
<div style="float: left">
<MyExtNet:TreePanel ID="TreePanel2" runat="server" CustomFullName="MyExtNet.MyControl.DataBaseStatic"
CustomMethod="GetData" CustomParams="-1" Width="200px" Height="300px" AutoScroll="true"
Lines="false">
</MyExtNet:TreePanel>
</div>
<div style="float: left">
<MyExtNet:TreePanel ID="TreePanel3" runat="server" CustomFullName="MyExtNet.MyControl.DataBase"
CustomMethod="GetData" CustomParams="208" Width="200px" Height="300px" AutoScroll="true"
Lines="false">
</MyExtNet:TreePanel>
</div>
</form>
</body>
</html>
其中,
- ID 为 TreePanel1,反射非静态类中的方法,获得全部数据,构造树形结构;
- ID 为 TreePanel2,反射静态类中的方法,获得全部数据,构造树形结构;
- ID 为 TreePanel3,反射非静态类中的方法,获得所有父节点为 208 下的全部数据,构造树形结构。
运行结果
其中,
- 第一个图,为 TreePanel1;
- 第二个图,为 TreePanel2;
- 第三个图,为 TreePanel3。