您的位置:首页 > 其它

Ext.Net 1.2.0_在 Web 应用程序中自定义 TreePanel 控件

2011-12-23 21:53 435 查看
本文内容

概述
演示自定义 TreePanel 控件
运行结果
说明
 

概述

当我最开始使用 VS 开发 ASP.NET Web 应用程序时,使用最多的就是用户控件(.ascx)。它的方便在于,可以将界面分割成一个个小的功能模块,也就是利用 ASP.NET 自带的控件组合成一个新的控件,然后在需要的界面“拖”进去就行。

这种方式,不仅对后台方便,对前台也是。比如,对于页面,以及页面的任何一个功能区域,我们都可以分成顶部、底部和中间内容部分,那么就可以对 CSS 做统一设置。

现在我使用 Ext.Net,虽然其 Demo 提供了 SimpleTask Demo,演示了如何自定义、封装一个 Ext.Net 控件,看上去很不错。但一是不熟悉,二是使用用户控件(.ascx)习惯了,而且似乎用户控件足够现在的项目了。

但某天,当我偶然用 Yahoo YSLOW 插件测试我的页面时,突然发现我的用户控件竟然出现了好几个 404 错误。虽然页面在运行时完全正常。我将用户控件需要的脚本,以外部文件方式添加到用户控件,不想将外部脚本在页面里引用,将来不好维护,同时,也不想直接将脚本代码嵌入到用户控件里。毕竟,外部文件可以被浏览器缓存,而嵌入代码则不能。因为,页面和用户控件初始化顺序的问题。

404 错误是个恶心的错误。它能让浏览器做很多无用功,消耗响应时间。我还是改程序吧~~~呵呵,针对目前的这个,用户控件的确存在一些问题。

本文演示如何利用 Ext.Net 封装一个自定义控件。它通常由两个文件、三部分组成:控件类文件和外部脚本文件。其中,控件类文件是一个分部类,分别实现控件的 UI 代码和逻辑代码。UI 代码负责创建控件标记;逻辑代码创建控件的客户端事件和服务器端事件。外部脚本文件用于在客户端操作控件。

 

演示自定义 TreePanel 控件

先看看封装后,在页面中引用自定义控件,代码如下:

[code]     [code]<%@ Page Language="C#" %>


 


<%@ Register Assembly="Ext.Net" Namespace="Ext.Net" TagPrefix="ext" %>


<%@ Register Assembly="ExtNetTreePanleCustomControl" Namespace="ExtNetTreePanleCustomControl.MyCustomControl"


TagPrefix="MyControl" %>


<!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="ScriptFiles" />


 


<script src="resources/myTreePanel.js" type="text/javascript"></script>


 


</head>


<body>


<form id="form1" runat="server">


<ext:ResourceManager ID="ResourceManager1" runat="server" InitScriptMode="Linked"


RemoveViewState="true" IDMode="Explicit" />


<MyControl:MyTreePanel ID="MyTreePanel1" runat="server" />


</form>


</body>


</html>

[/code]
[/code]

其中,"<MyControl:MyTreePanel ID="MyTreePanel1" runat="server" />" 是自定义的 TreePanel 控件。

自定义控件的分部类 MyTreePanel,文件名分别为 MyTreePanelLogic.cs 和 MyTreePanelUI.cs

[code]using System;


using System.Collections.Generic;


using System.Linq;


 


using Ext.Net.Utilities;


using Ext.Net;


 


namespace ExtNetTreePanleCustomControl.MyCustomControl


{


[DirectMethodProxyID(IDMode = DirectMethodProxyIDMode.None)]


public partial class MyTreePanel


{


public const string SCOPE = "MyCustomControl.MyTreePanel";


 


private void InitLogic()


{


this.Listeners.Render.Fn = MyTreePanel.SCOPE + ".init";


this.Listeners.Render.Scope = MyTreePanel.SCOPE;


this.Listeners.CheckChange.Handler = MyTreePanel.SCOPE + ".SelectParentChildNodes(node,checked);";


 


 


Ext.Net.Button button = new Ext.Net.Button();


button.ID = "btnGet";


button.Text = "获得勾选";


button.Listeners.Click.Handler = MyTreePanel.SCOPE + ".getSelectedNode(#{" + this.ID + "})";


this.Buttons.Add(button);


button = new Ext.Net.Button();


button.ID = "btnClear";


button.Text = "清除勾选";


button.Listeners.Click.Handler = MyTreePanel.SCOPE + ".clearSelectedNode(#{" + this.ID + "})";


this.Buttons.Add(button);


}


}


}

[/code]

 


[code][code]using System;


using System.Collections.Generic;


using System.ComponentModel;


using System.Linq;


using System.Xml.Serialization;


using Ext.Net;


using Newtonsoft.Json;


 


namespace ExtNetTreePanleCustomControl.MyCustomControl


{


public partial class MyTreePanel : TreePanel


{


public MyTreePanel()


{


this.ID = "MyTreePanel1";


this.Title = "MyTreePanel";


this.Width = System.Web.UI.WebControls.Unit.Pixel(300);


this.Height = System.Web.UI.WebControls.Unit.Pixel(400);


this.UseArrows = true;


this.AutoScroll = true;


this.Animate = true;


this.EnableDD = true;


this.ContainerScroll = true;


this.RootVisible = false;


 


this.LoadMask.ShowMask = true;


 


this.SelectionModel.Add(new Ext.Net.DefaultSelectionModel());


 


this.BuildTree();


this.InitLogic();


}


 


private void BuildTree()


{


Ext.Net.TreeNode root = new Ext.Net.TreeNode("Composers");


root.Expanded = true;


this.Root.Add(root);


 


 


List<Composer> composers = MyData.GetData();


 


foreach (Composer composer in composers)


{


Ext.Net.TreeNode composerNode = new Ext.Net.TreeNode(composer.Name, Icon.UserGray);


composerNode.Checked = Ext.Net.ThreeStateBool.False;


composerNode.Leaf = false;


composerNode.Icon = Ext.Net.Icon.Folder;


root.Nodes.Add(composerNode);


 


foreach (Composition composition in composer.Compositions)


{


Ext.Net.TreeNode compositionNode = new Ext.Net.TreeNode(composition.Type.ToString());


compositionNode.Checked = Ext.Net.ThreeStateBool.False;


compositionNode.Leaf = false;


compositionNode.Icon = Ext.Net.Icon.Folder;


composerNode.Nodes.Add(compositionNode);


 


foreach (Piece piece in composition.Pieces)


{


Ext.Net.TreeNode pieceNode = new Ext.Net.TreeNode(piece.Title, Icon.Music);


pieceNode.Checked = Ext.Net.ThreeStateBool.False;


pieceNode.Leaf = true;


compositionNode.Nodes.Add(pieceNode);


}


}


}


}


}


}

[/code]
[/code]

数据

[code]using System;


using System.Collections;


using System.Collections.Generic;


using System.Globalization;


using System.Web;


using System.Xml;


using Ext.Net;


 


namespace ExtNetTreePanleCustomControl


{


public class Composer


{


public Composer(string name) { this.Name = name; }


public string Name { get; set; }


 


private List<Composition> compositions;


public List<Composition> Compositions


{


get


{


if (this.compositions == null)


{


this.compositions = new List<Composition>();


}


return this.compositions;


}


}


}


 


public class Composition


{


public Composition() { }


 


public Composition(CompositionType type)


{


this.Type = type;


}


 


public CompositionType Type { get; set; }


 


private List<Piece> pieces;


public List<Piece> Pieces


{


get


{


if (this.pieces == null)


{


this.pieces = new List<Piece>();


}


return this.pieces;


}


}


}


 


public class Piece


{


public Piece() { }


 


public Piece(string title)


{


this.Title = title;


}


 


public string Title { get; set; }


}


 


public enum CompositionType


{


Concertos,


Quartets,


Sonatas,


Symphonies


}


 


public class MyData


{


public static List<Composer> GetData()


{


Composer beethoven = new Composer("Beethoven");


 


Composition beethovenConcertos = new Composition(CompositionType.Concertos);


Composition beethovenQuartets = new Composition(CompositionType.Quartets);


Composition beethovenSonatas = new Composition(CompositionType.Sonatas);


Composition beethovenSymphonies = new Composition(CompositionType.Symphonies);


 


beethovenConcertos.Pieces.AddRange(new List<Piece> {


new Piece{ Title = "No. 1 - C" },


new Piece{ Title = "No. 2 - B-Flat Major" },


new Piece{ Title = "No. 3 - C Minor" },


new Piece{ Title = "No. 4 - G Major" },


new Piece{ Title = "No. 5 - E-Flat Major" }


});


 


beethovenQuartets.Pieces.AddRange(new List<Piece> {


new Piece{ Title = "Six String Quartets" },


new Piece{ Title = "Three String Quartets" },


new Piece{ Title = "Grosse Fugue for String Quartets" }


});


 


beethovenSonatas.Pieces.AddRange(new List<Piece> {


new Piece{ Title = "Sonata in A Minor" },


new Piece{ Title = "sonata in F Major" }


});


 


beethovenSymphonies.Pieces.AddRange(new List<Piece> {


new Piece{ Title = "No. 1 - C Major" },


new Piece{ Title = "No. 2 - D Major" },


new Piece{ Title = "No. 3 - E-Flat Major" },


new Piece{ Title = "No. 4 - B-Flat Major" },


new Piece{ Title = "No. 5 - C Minor" },


new Piece{ Title = "No. 6 - F Major" },


new Piece{ Title = "No. 7 - A Major" },


new Piece{ Title = "No. 8 - F Major" },


new Piece{ Title = "No. 9 - D Minor" }


});


 


beethoven.Compositions.AddRange(new List<Composition>{


beethovenConcertos,


beethovenQuartets,


beethovenSonatas,


beethovenSymphonies


});


 


 


Composer brahms = new Composer("Brahms");


 


Composition brahmsConcertos = new Composition(CompositionType.Concertos);


Composition brahmsQuartets = new Composition(CompositionType.Quartets);


Composition brahmsSonatas = new Composition(CompositionType.Sonatas);


Composition brahmsSymphonies = new Composition(CompositionType.Symphonies);


 


brahmsConcertos.Pieces.AddRange(new List<Piece> {


new Piece{ Title = "Violin Concerto" },


new Piece{ Title = "Double Concerto - A Minor" },


new Piece{ Title = "Piano Concerto No. 1 - D Minor" },


new Piece{ Title = "Piano Concerto No. 2 - B-Flat Major" }


});


 


brahmsQuartets.Pieces.AddRange(new List<Piece> {


new Piece{ Title = "Piano Quartet No. 1 - G Minor" },


new Piece{ Title = "Piano Quartet No. 2 - A Major" },


new Piece{ Title = "Piano Quartet No. 3 - C Minor" },


new Piece{ Title = "Piano Quartet No. 3 - B-Flat Minor" }


});


 


brahmsSonatas.Pieces.AddRange(new List<Piece> {


new Piece{ Title = "Two Sonatas for Clarinet - F Minor" },


new Piece{ Title = "Two Sonatas for Clarinet - E-Flat Major" }


});


 


brahmsSymphonies.Pieces.AddRange(new List<Piece> {


new Piece{ Title = "No. 1 - C Minor" },


new Piece{ Title = "No. 2 - D Minor" },


new Piece{ Title = "No. 3 - F Major" },


new Piece{ Title = "No. 4 - E Minor" }


});


 


brahms.Compositions.AddRange(new List<Composition>{


brahmsConcertos,


brahmsQuartets,


brahmsSonatas,


brahmsSymphonies


});


 


 


Composer mozart = new Composer("Mozart");


 


Composition mozartConcertos = new Composition(CompositionType.Concertos);


 


mozartConcertos.Pieces.AddRange(new List<Piece> {


new Piece{ Title = "Piano Concerto No. 12" },


new Piece{ Title = "Piano Concerto No. 17" },


new Piece{ Title = "Clarinet Concerto" },


new Piece{ Title = "Violin Concerto No. 5" },


new Piece{ Title = "Violin Concerto No. 4" }


});


 


mozart.Compositions.Add(mozartConcertos);


 


return new List<Composer> { beethoven, brahms, mozart };


}


}


}

[/code]

外部脚本文件 myTreePanel.js

[code]Ext.ns("MyCustomControl");


 


// ------------------MyTreePanel----------------------------------


MyCustomControl.MyTreePanel = {


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 != 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(tree) {


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(tree) {


tree.clearChecked();


}


};

[/code]

 

运行结果









 

说明

有几点值得注意:

标记 <ext:ResourcePlaceHolder ID="ResourcePlaceHolder1" runat="server" Mode="ScriptFiles" />,Mode="ScriptFiles" 是为了 MyTreePanel 呈现后,保证页面在正确的时机加载,并执行 MyCustomControl.MyTreePanel.init 方法,初始化其 tr 属性,以便在客户端操作该控件;

public const string SCOPE = "MyCustomControl.MyTreePanel"; 语句,配合脚本的 Ext.ns("MyCustomControl"); 以及 MyCustomControl.MyTreePanel = { … },在脚本创建命名空间和 MyTreePanel 类。

这种方式在很大程度上提高页面性能,便于日后维护该控件。

 

下载 Demo
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: