天天看點

擴充GridView控件--增加選擇列

GridView是asp.net 2.0中,最常用、最好用的伺服器控件之一;但是,為了讓它更适應于我們具體的項目,我們很多時候,需要對它進行一些特殊操作。

如,實作如下效果

擴充GridView控件--增加選擇列

當然,我承認,實作如上效果并不複雜,

1、增加一個模版列放置複選框;

2、合并底部(footer)并放置三個LinkButton,即全選、反選、取消;并寫相應事件,使其可以操作各行中的複選框;

3、然後在OnRowDataBound事件中,給各個行加上JavaScript事件,使各個資料行可以響應滑鼠懸停,以及單擊事件;

4、當通過其它的操作(如點選删除按鈕)來操作資料行時,用foreach周遊各資料行即可;

問題是,我們的項目中,會非常頻繁的用到這個效果,作為一個懶人,每次要拷貝代碼,實在是太麻煩了。寫一個增強的GridView控件,才是明智之舉;

如上效果所示,這個增強GridView應該具備以下功能:

1、拖上來就能用,自帶一個選擇列;這個選擇列要能夠綁定資料(可選);也就是說,增強控件隻能比以前更友善,不能更複雜。

2、footer自動合并,并帶三個LinkButton;對複選框操作采用JavaScript方法,在用戶端執行,這樣無須重新整理頁面,操作更流暢;

3、能夠自動取出選中的行,不必再foreach周遊;

4、帶一些參數,可以選擇是否顯示“選擇列”,以及取選中行的主鍵值;

為了實作以上效果,要寫C#,也要寫JavaScript與Css;

例如,動态增加模版列,當然得寫C#代碼操作;利用控件的OnInit事件;

而資料行的滑鼠懸停與單擊,當然得寫JavaScript,用它來操作加載Css樣式;這裡我用了Jquery架構。

我在這裡把主要的C#代碼拿出來供學習吧。關鍵的地方我做了描述,當然,裡面有一些代碼寫得有備援,也是自己懶,不想在用戶端做太多判斷,直接辨別了資料行,如e.Row.Attributes.Add("RowType","DataRow");,之類的,都是為友善js在用戶端判斷。

代碼如下:

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Text;

using System.Web;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.Web.UI.HtmlControls;

namespace Company.CustomControl

{

    [DefaultProperty("Text")]

    [ToolboxData("<{0}:GridView runat=server></{0}:GridView>")]

    public class GridView : System.Web.UI.WebControls.GridView

    {

        #region 屬性

        [Bindable(true)]

        [Category("Appearance")]

        [DefaultValue("用于選擇的複選框所在資料列的,資料列名稱,即綁定值")]

        [Localizable(true)]

        public string SelectBoxKeyName

        {

            get

            {

                String s = (String)ViewState["SelectBoxKeyName"];

                return ((s == null) ? "SelectBox" : s);

            }

            set

                ViewState["SelectBoxKeyName"] = value;

        }

        [DefaultValue("是否顯示用于選擇的複選框的資料列")]

        public bool ShowSelectBox

                String s = (String)ViewState["ShowSelectBox"];

                return Convert.ToBoolean(((s == null) ? "True" : s));

                ViewState["ShowSelectBox"] = value.ToString();

        /// <summary>

        /// 擷取選中資料行的主鍵值

        /// </summary>

        [DefaultValue(" 擷取選中資料行的主鍵值")]

        public string GetKeyValues

                if (this.DataKeyNames.Length < 1)

                {

                    return "";

                }

                string tmp = "";

                foreach (GridViewRow vr in this.Rows)

                    if (vr.RowType == DataControlRowType.DataRow)

                    {

                        CheckBox cb = (CheckBox)vr.FindControl(this.SelectBoxKeyName);

                        if (cb.Checked)

                        {

                            tmp += this.DataKeys[vr.RowIndex].Value.ToString() + ",";

                        }

                    }

                if (tmp.IndexOf(",") > -1)

                    tmp = tmp.Substring(0, tmp.LastIndexOf(","));

                return tmp;

        #endregion

        protected override void OnDataBound(EventArgs e)

            if (this.CssClass == String.Empty)

                this.CssClass = "GridView";

            base.OnDataBound(e);

        protected override void OnInit(EventArgs e)

            //綁定選擇框的列

            if (this.ShowSelectBox)

                TemplateField dcf = new TemplateField();

                dcf.HeaderText = "選擇";

                CheckTemplate mt = new CheckTemplate(this.SelectBoxKeyName);

                dcf.ItemTemplate = mt;

                this.Columns.Insert(0, dcf);

            base.OnInit(e);

        protected override void OnRowDataBound(GridViewRowEventArgs e)

            //當為資料行時

            if (e.Row.RowType == DataControlRowType.DataRow)

                e.Row.Attributes.Add("RowType","DataRow");

                //取主鍵的值

                if (this.DataKeyNames != null && this.DataKeyNames.Length>0)

                    string val = this.DataKeys[e.Row.RowIndex].Value.ToString();

                    e.Row.Attributes.Add("DataKey", val);

                e.Row.Cells[0].Attributes.Add("ItemType","SelectBox");

            //底部欄的跨列

            if (e.Row.RowType == DataControlRowType.Footer)

                e.Row.Attributes.Add("RowType", "Footer");

                int col = e.Row.Cells.Count;

                e.Row.Cells[0].ColumnSpan = col;

                while (--col > 0)

                    e.Row.Cells[col].Visible = false;

                e.Row.Cells[0].Attributes.Add("ItemType", "SelectHandler");

                e.Row.Cells[0].Text = "全選、反選、取消";

            base.OnRowDataBound(e);

        }       

    }

    /// <summary>

    /// 用于載入複選框的類,該類很重要,是用于自定義GridView模版列的必然方法;

    /// </summary>

    public class CheckTemplate : ITemplate

        private string colname;

        public CheckTemplate(string colname)

            this.colname = colname;

        public void InstantiateIn(Control container)

            CheckBox cb = new CheckBox();

            cb.ID = colname;

            cb.CssClass = colname;

            cb.Attributes.Add("ControlType", "SelectBox");

            cb.DataBinding += new EventHandler(this.OnDataBinding);

            container.Controls.Add(cb);

        public void OnDataBinding(object sender, EventArgs e)

        {           

            try

                //用于資料綁定

                CheckBox cb = (CheckBox)sender;

                GridViewRow container = (GridViewRow)cb.NamingContainer;

                //如果存在該資料列,則綁定;

                cb.Checked = Convert.ToBoolean(((DataRowView)container.DataItem)[colname].ToString());

            catch

                  //我不是有意要寫try,隻是當SelectBoxKeyName屬性為空時,即使用者并不想給選擇列綁定資料時,這裡不至于出錯;

                 //如果SelectBoxKeyName屬性不為空,其資料會自動綁定到選擇列上。

}

上面的控件,增加了三個屬性;

SelectBoxKeyName:這個是對選擇列進行資料綁定時的鍵值,如DataTable的列名;這個可以不填的。

ShowSelectBox:是否顯示的選擇列,預設為顯示;

GetKeyValues:擷取選中資料行的主鍵值;如果沒有主鍵,或沒有選中行,則傳回空字元,否則傳回主鍵清單字元串,用逗号分隔;如10,20,55,56;

使用很簡單,asp.net頁面中代碼如下

<%@ Register Assembly="Company.CustomControl" Namespace="Company.CustomControl" TagPrefix="cc1" %>

<cc1:GridView ID="GridView1" runat="server" ShowFooter="True">

        </cc1:GridView>

綁定資料後,就顯示出如頂部圖中的效果。

我抽空把它整理出來,單獨放到一個項目中,做個完整示例,發上來吧。以上代碼,供參考學習;

完整示例做好了(vs2005 sp1):

​​GridViewDemo.rar​​

繼續閱讀