TreeView既强大又好用。为了让它更强大、更好用,我们来写一个继承自TreeView的控件。
[×××]


扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)


作者:webabcd


介绍
扩展TreeView控件:
联动复选框(复选框的全选和取消全选)。选中指定的父复选框,则设置其所有子复选框为选中状态;取消选中指定的父复选框,则设置其所有子复选框为取消选中状态。如果某父复选框的所有子复选框为均选中状态,则设置该父复选框为选中状态;如果某复选框的所有子复选框至少有一个为取消选中状态,则设置该父复选框为取消选中状态

使用方法(设置属性):
AllowCascadeCheckbox - 是否启用联动复选框功能


关键代码
相关的js
//----------------------------
// http://webabcd.cnblogs.com/
//----------------------------

/*Helper 开始*/
String.prototype.yy_stv_startsWith = function(s)
{        
/// <summary>StartsWith()</summary>

        var reg = new RegExp("^" + s);        
        return reg.test(this);
}

function yy_stv_addEvent(obj, evtType, fn)    
{
/// <summary>绑定事件</summary>

        // FF
        if (obj.addEventListener)
        {
                obj.addEventListener(evtType, fn, true);
                return true;
        }
        // IE
        else if (obj.attachEvent)
        {
                var r = obj.attachEvent("on" + evtType, fn);
                return r;
        }
        else
        {
                return false;
        }        
}
/*Helper 结束*/


/*联动复选框 开始*/
var yy_stv_ccTreeView_pre = new Array(); // cs中动态向其灌数据(TreeView内控件ID的前缀数组)

function yy_stv_ccClickCheckbox(e)    
{
/// <summary>单击复选框时</summary>

        var evt = e || window.event; // FF || IE
        var obj = evt.target || evt.srcElement    // FF || IE
        
        yy_stv_foreachChildCheckbox(obj);
        yy_stv_foreachParentCheckbox(obj);
}


function yy_stv_checkParentCheckbox(table, checked)
{
/// <summary>设置父复选框的状态</summary>

        var nodes = table.parentNode.parentNode.childNodes;
                
        for (var i=1; i<nodes.length; i++)
        {
                if (nodes[i] == table.parentNode)
                {
                        if (typeof(nodes[i-1]) == 'undefined' || typeof(nodes[i-1].rows) == 'undefined') return;

                        for (var x=0; x < nodes[i-1].rows.length; x++)
                        {
                                for (var j=0; j < nodes[i-1].rows[x].cells.length; j++)
                                {
                                        // debugger;
                                        var chk = nodes[i-1].rows[x].cells[j].childNodes[0];
                                        if (typeof(chk) != 'undefined' && chk.tagName == "INPUT" && chk.type == "checkbox")    
                                        {
                                                chk.checked = checked;
                                                yy_stv_foreachParentCheckbox(nodes[i-1]);
                                                return;
                                        }
                                }
                        }
                }
        }
}

function yy_stv_foreachChildCheckbox(obj)
{        
/// <summary>单击父复选框时,设置其子复选框的选中状态</summary>

        var checked;
        
        if (obj.tagName == "INPUT" && obj.type == "checkbox")    
        {
                checked = obj.checked;
                do
                {
                        obj = obj.parentNode;
                }    
                while (obj.tagName != "TABLE")
        }
        
        var nodes = obj.parentNode.childNodes;
                
        for (var i=0; i<nodes.length - 1; i++)
        {
                if (nodes[i] == obj && nodes[i + 1].tagName == "DIV")
                {
                        var elements = nodes[i+1].getElementsByTagName("INPUT");
                        
                        for (j=0; j< elements.length; j++)    
                        {                
                                if (elements[j].type == 'checkbox')    
                                {
                                        elements[j].checked = checked;
                                }
                        }        
                }
        }
}

function yy_stv_foreachParentCheckbox(obj)
{        
/// <summary>单击某一复选框时,设置其父复选框的选中状态</summary>

        var checkedNum = 0;
        var uncheckedNum = 0;
        
        if (obj.tagName == "INPUT" && obj.type == "checkbox")    
        {
                do
                {
                        obj = obj.parentNode;
                }    
                while (obj.tagName != "TABLE")
        }
                                
        var tables = obj.parentNode.getElementsByTagName("TABLE");
            
        if (typeof(tables) == 'undefined') return;
                
        for (var i=0; i < tables.length; i++)
        {                
                for (var x=0; x < tables[i].rows.length; x++)
                {
                        for (var j=0; j < tables[i].rows[x].cells.length; j++)
                        {
                                var chk = tables[i].rows[x].cells[j].childNodes[0];
                                if (typeof(chk) != 'undefined' && chk.tagName == "INPUT" && chk.type == "checkbox")    
                                {
                                        if (chk.checked)
                                                checkedNum ++;
                                        else
                                                uncheckedNum ++;
                                }
                        }
                }
        }
        
        if (uncheckedNum == 0)
        {
                yy_stv_checkParentCheckbox(obj, true);
        }
        else
        {
                yy_stv_checkParentCheckbox(obj, false);
        }
}


function yy_stv_attachCheckboxClickListener()
{
/// <summary>监听所有联动复选框的单击事件</summary>

        var elements =    document.getElementsByTagName("INPUT");
        
        for (i=0; i< elements.length; i++)    
        {                
                if (elements[i].type == 'checkbox')    
                {
                        for (j=0; j<yy_stv_ccTreeView_pre.length; j++)
                        {
                                if (elements[i].id.yy_stv_startsWith(yy_stv_ccTreeView_pre[j]))
                                {
                                        yy_stv_addEvent(elements[i], 'click', yy_stv_ccClickCheckbox);    
                                        break;
                                }
                        }
                }
        }        
}

if (document.all)
{
        window.attachEvent(' yy_stv_attachCheckboxClickListener);
}
else
{
        window.addEventListener('load', yy_stv_attachCheckboxClickListener, false);
}
/*联动复选框 结束*/
 
说明:
1、页面加载时为指定的TreeView的所有复选框绑定单击事件(根据复选框的前缀判断其是否属于指定的复选框)
2、单击某复选框,则遍历其所有子复选框,并进行相应的操作。同时,遍历同级复选框,并对它们的父复选框进行操作,然后再遍历它们的父复选框的同级的复选框,以此类推往上走。

相关的属性
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeViewusing System;
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeViewusing System.Collections.Generic;
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeViewusing System.Text;
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeViewusing System.ComponentModel;
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeViewusing System.Web.UI;
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeViewnamespace YYControls
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView{
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView        /// <summary>
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView        /// SmartTreeView类的属性部分
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView        /// </summary>
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView        public partial class SmartTreeView
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView        {
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView                private bool _allowCascadeCheckbox;
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView                /// <summary>
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView                /// 是否启用联动复选框功能
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView                /// </summary>
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView                [
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView                Browsable(true),
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView                Description("是否启用联动复选框功能"),
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView                Category("扩展"),
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView                DefaultValue(false)
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView                ]
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView                public virtual bool AllowCascadeCheckbox
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView                {
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView                        get { return _allowCascadeCheckbox; }
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView                        set { _allowCascadeCheckbox = value; }
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView                }
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView        }
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView}
 
相关的cs
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeViewusing System;
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeViewusing System.Collections.Generic;
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeViewusing System.Text;
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeViewusing System.Web.UI.WebControls;
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeViewusing System.Web.UI;
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeViewnamespace YYControls.SmartTreeViewFunction
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView{
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView        /// <summary>
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView        /// 扩展功能:联动复选框
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView        /// </summary>
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView        public class CascadeCheckboxFunction : ExtendFunction
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView        {
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView                /// <summary>
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView                /// 构造函数
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView                /// </summary>
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView                public CascadeCheckboxFunction()
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView                        : base()
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView                {
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView                }
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView                /// <summary>
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView                /// 构造函数
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView                /// </summary>
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView                /// <param name="stv">SmartTreeView对象</param>
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView                public CascadeCheckboxFunction(SmartTreeView stv)
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView                        : base(stv)
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView                {
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView                }
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView                /// <summary>
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView                /// 扩展功能的实现
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView                /// </summary>
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView                protected override void Execute()
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView                {
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView                        this._stv.PreRender += new EventHandler(_stv_PreRender);
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView                }
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView                /// <summary>
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView                /// SmartTreeView的PreRender事件
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView                /// </summary>
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView                /// <param name="sender"></param>
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView                /// <param name="e"></param>
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView                void _stv_PreRender(object sender, EventArgs e)
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView                {
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView                        // 注册向数组中添加成员的脚本
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView                        if (!this._stv.Page.ClientScript.IsClientScriptBlockRegistered(String.Format("yy_stv_cascadeCheckbox_{0}", this._stv.ID)))
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView                        {
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView                                this._stv.Page.ClientScript.RegisterClientScriptBlock
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView                                (
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView                                        this.GetType(),
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView                                        String.Format("yy_stv_cascadeCheckbox_{0}", this._stv.ID),
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView                                        String.Format("yy_stv_ccTreeView_pre.push('{0}');", Helper.Common.GetChildControlPrefix(this._stv)),
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView                                        true
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView                                );
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView                        }
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView                }
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView        }
扩展TreeView控件(1) - 联动复选框(复选框的全选和取消全选)_TreeView}