扩展GridView控件(五)——固定表头、指定行或指定列

    技术2022-05-11  64

    扩展GridView控件(五)——固定表头、指定行或指定列

    介绍平时使用GridView的时候会有固定表头、指定行或指定列的需求,就像Excel冻结行、列那样。其实我们可以用CSS来搞定。扩展一下GridView,通过设置几个属性来达到这样的功能。控件开发1、新建一个继承自GridView的类,另外为了保持滚动条状态,还要继承IPostBackDataHandler接口

         /// <summary>    /// 继承自GridView    /// </summary>     [ToolboxData( @" <{0}:SmartGridView runat='server'></{0}:SmartGridView> " )]     public   class  SmartGridView : GridView, IPostBackDataHandler     {    }

    2、新建一个FixRowCol类,有七个属性

    using  System; using  System.Collections.Generic; using  System.Text; using  System.ComponentModel; namespace  YYControls.SmartGridView {    /// <summary>    /// 固定表头、指定行或指定列的实体类    /// </summary>    [TypeConverter(typeof(ExpandableObjectConverter))]    public class FixRowCol    {        private bool _isFixHeader;        /// <summary>        /// 固定表头否?        /// </summary>        [Description("固定表头否?"), Category("扩展"), DefaultValue(false), NotifyParentProperty(true)]        public virtual bool IsFixHeader        {            get return _isFixHeader; }            set { _isFixHeader = value; }        }        private bool _isFixPager;        /// <summary>        /// 固定分页行否?        /// </summary>        [Description("固定分页行否?"), Category("扩展"), DefaultValue(false), NotifyParentProperty(true)]        public virtual bool IsFixPager        {            get return _isFixPager; }            set { _isFixPager = value; }        }        private string _fixRowIndices;        /// <summary>        /// 需要固定的行的索引(用逗号“,”分隔)        /// </summary>        [Description("需要固定的行的索引(用逗号“,”分隔)"), Category("扩展"), NotifyParentProperty(true)]        public virtual string FixRowIndices        {            get return _fixRowIndices; }            set { _fixRowIndices = value; }        }        private string _fixColumnIndices;        /// <summary>        /// 需要固定的列的索引(用逗号“,”分隔)        /// </summary>        [Description("需要固定的列的索引(用逗号“,”分隔)"), Category("扩展"), NotifyParentProperty(true)]        public virtual string FixColumnIndices        {            get return _fixColumnIndices; }            set { _fixColumnIndices = value; }        }        private System.Web.UI.WebControls.Unit _tableWidth;        /// <summary>        /// 表格的宽度        /// </summary>        [Description("表格的宽度"), Category("扩展"), NotifyParentProperty(true)]        public System.Web.UI.WebControls.Unit TableWidth        {            get return _tableWidth; }            set { _tableWidth = value; }        }        private System.Web.UI.WebControls.Unit _tableHeight;        /// <summary>        /// 表格的高度        /// </summary>        [Description("表格的高度"), Category("扩展"), NotifyParentProperty(true)]        public System.Web.UI.WebControls.Unit TableHeight        {            get return _tableHeight; }            set { _tableHeight = value; }        }        private bool _enableScrollState;        /// <summary>        /// 是否保持滚动条的状态        /// </summary>        [Description("是否保持滚动条的状态"), Category("扩展"), DefaultValue(false), NotifyParentProperty(true)]        public bool EnableScrollState        {            get return _enableScrollState; }            set { _enableScrollState = value; }        }        /// <summary>        /// ToString();        /// </summary>        /// <returns></returns>        public override string ToString()        {            return "FixRowCol";        }    }}

    3、在继承自GridView的类中加一个复杂对象属性,该复杂对象就是第2步创建的那个FixRowCol

             private  FixRowCol _fixRowCol;         /// <summary>        /// 固定表头、指定行或指定列        /// </summary>         [        Description( " 固定表头、指定行或指定列 " ),        Category( " 扩展 " ),        DefaultValue( "" ),        DesignerSerializationVisibility(DesignerSerializationVisibility.Content),        PersistenceMode(PersistenceMode.InnerProperty)        ]         public   virtual  FixRowCol FixRowCol         {            get            {                if (_fixRowCol == null)                {                    _fixRowCol = new FixRowCol();                }                return _fixRowCol;            }        }

    4、重写OnRowDataBound以设置每个单元格的样式,从而实现固定表头、指定行或指定列的功能。

             /// <summary>        /// OnRowDataBound        /// </summary>        /// <param name="e"></param>          protected   override   void  OnRowDataBound(GridViewRowEventArgs e)         {            if (e.Row.RowType == DataControlRowType.Pager)            {                if (FixRowCol.IsFixPager)                {                    if (this.PagerSettings.Position == PagerPosition.Top || (this.PagerSettings.Position == PagerPosition.TopAndBottom && _isTopPager))                    {                        // TopPager固定行和列                        e.Row.Cells[0].Attributes.Add("style""z-index:999; position: relative; top: expression(this.offsetParent.scrollTop); left: expression(this.offsetParent.scrollLeft);");                        // 现在是TopPager,之后就是BottomPager了,所以设置_isTopPager为false                        _isTopPager = false;                    }                    else if (this.PagerSettings.Position == PagerPosition.TopAndBottom && !_isTopPager)                    {                        // BottomPager只固定列                        e.Row.Cells[0].Attributes.Add("style""z-index:999; position: relative; left: expression(this.offsetParent.scrollLeft);");                        // 现在是BottomPager,之后就是TopPager了,所以设置_isTopPager为true                        _isTopPager = true;                    }                }            }            if (e.Row.RowType == DataControlRowType.DataRow || e.Row.RowType == DataControlRowType.Header)            {                // 给每一个指定固定的列的单元格加上css属性                if (!String.IsNullOrEmpty(FixRowCol.FixColumnIndices))                {                    // 列索引                    foreach (string s in FixRowCol.FixColumnIndices.Split(','))                    {                        int i;                        if (!Int32.TryParse(s, out i))                            throw new ArgumentException("FixColumnIndices""含有非整形的字符");                        if (i > e.Row.Cells.Count)                            throw new ArgumentOutOfRangeException("FixColumnIndices""溢出");                        e.Row.Cells[i].Attributes.Add("style""position: relative; left: expression(this.offsetParent.scrollLeft);");                    }                }                bool isFixRow = false// 当前行是否固定                if (FixRowCol.IsFixHeader && e.Row.RowType == DataControlRowType.Header)                {                    isFixRow = true;                }                if (!String.IsNullOrEmpty(FixRowCol.FixRowIndices) && e.Row.RowType == DataControlRowType.DataRow)                {                    // 行索引                    foreach (string s in FixRowCol.FixRowIndices.Split(','))                    {                        int i;                        if (!Int32.TryParse(s, out i))                            throw new ArgumentException("FixRowIndices""含有非整形的字符");                        if (i > e.Row.Cells.Count)                            throw new ArgumentOutOfRangeException("FixRowIndices""溢出");                        if (i == e.Row.RowIndex)                        {                            isFixRow = true;                            break;                        }                    }                }                // 固定该行                if (isFixRow)                {                    // 该行的每一个单元格                    for (int j = 0; j < e.Row.Cells.Count; j++)                    {                        // 该单元格不属于固定列                        if (String.IsNullOrEmpty(e.Row.Cells[j].Attributes["style"]) || e.Row.Cells[j].Attributes["style"].IndexOf("position: relative;"== -1)                        {                            e.Row.Cells[j].Attributes.Add("style"" position: relative; top: expression(this.offsetParent.scrollTop);");                        }                        // 该单元格属于固定列                        else                        {                            e.Row.Cells[j].Attributes.Add("style", e.Row.Cells[j].Attributes["style"+ "top: expression(this.offsetParent.scrollTop); z-index: 666;");                        }                    }                }            }            base.OnRowDataBound(e);        }

    5、增加两个私有变量

             /// <summary>        /// 如果固定行、列的话 滚动条的x位置        /// </summary>          private   int  _yy_SmartGridView_x;         /// <summary>        /// 如果固定行、列的话 滚动条的y位置        /// </summary>          private   int  _yy_SmartGridView_y;

    6、重写GridView的OnPreRender方法,用于注册两个HiddenField,以及注册设置GridView的滚动条的位置的javascript代码

             /// <summary>        /// OnPreRender        /// </summary>        /// <param name="e"></param>          protected   override   void  OnPreRender(EventArgs e)         {            if (FixRowCol.EnableScrollState)            {                // 滚动条x位置                Page.ClientScript.RegisterHiddenField("yy_SmartGridView_x", _yy_SmartGridView_x.ToString());                // 滚动条y位置                Page.ClientScript.RegisterHiddenField("yy_SmartGridView_y", _yy_SmartGridView_y.ToString());                // 设置GridView的滚动条的位置                Page.ClientScript.RegisterStartupScript(                    this.GetType(),                    "jsSetScroll""<script type=/"text/javascript/">document.getElementById('yy_ScrollDiv').scrollLeft=" + _yy_SmartGridView_x + ";document.getElementById('yy_ScrollDiv').scrollTop=" + _yy_SmartGridView_y + ";</script>"                    );                // 将控件注册为要求在页回发至服务器时进行回发处理的控件                if (Page != null) Page.RegisterRequiresPostBack(this);            }            base.OnPreRender(e);        }

    7、重写GridView的Render方法,将GridView用一个div包裹起来。

             /// <summary>        /// Render        /// </summary>        /// <param name="writer"></param>          protected   override   void  Render(HtmlTextWriter writer)         {            // 给GridView一个容器 <div>            if (!FixRowCol.TableWidth.IsEmpty || !FixRowCol.TableHeight.IsEmpty)            {                if (FixRowCol.TableWidth.IsEmpty) FixRowCol.TableWidth = new Unit(100, UnitType.Percentage);                if (FixRowCol.TableHeight.IsEmpty) FixRowCol.TableHeight = new Unit(100, UnitType.Percentage);                writer.Write("<div id='yy_ScrollDiv' style=/"overflow: auto; width: "                    + FixRowCol.TableWidth.ToString() + "; height: "                    + FixRowCol.TableHeight.ToString() + "; position: relative;/" ");                // 如果保持滚动条的状态的话,用隐藏字段记录滚动条的位置                if (FixRowCol.EnableScrollState)                {                    writer.Write("οnscrοll=/"document.getElementById('yy_SmartGridView_x').value = this.scrollLeft; document.getElementById('yy_SmartGridView_y').value = this.scrollTop;/">");                }                else                {                    writer.Write(">");                }            }            base.Render(writer);            // </div> 结束            if (!FixRowCol.TableWidth.IsEmpty || !FixRowCol.TableHeight.IsEmpty)            {                writer.Write("</div>");            }        }

    8、获取存储了滚条位置信息的HiddenField的值

             void  IPostBackDataHandler.RaisePostDataChangedEvent()         {        }          bool  IPostBackDataHandler.LoadPostData( string  postDataKey, NameValueCollection postCollection)         {            // 获取两个保存了 固定行、列后 的GridView滚动条的位置信息            _yy_SmartGridView_x = String.IsNullOrEmpty(postCollection["yy_SmartGridView_x"]) ? 0 : Convert.ToInt32(postCollection["yy_SmartGridView_x"]);            _yy_SmartGridView_y = String.IsNullOrEmpty(postCollection["yy_SmartGridView_y"]) ? 0 : Convert.ToInt32(postCollection["yy_SmartGridView_y"]);            return false;        }

    控件使用添加这个控件到工具箱里,然后拖拽到webform上,设置其FixRowCol下的7个属性即可。IsFixHeader是固定表头否?;IsFixPager是固定分页行否?;FixRowIndices是需要固定的行的索引(用逗号“,”分隔);FixColumnIndices是需要固定的列的索引(用逗号“,”分隔);TableWidth是表格的宽度;TableHeight是表格的高度;EnableScrollState为是否保持滚动条的状态ObjData.cs

    using  System; using  System.Data; using  System.Configuration; using  System.Web; using  System.Web.Security; using  System.Web.UI; using  System.Web.UI.WebControls; using  System.Web.UI.WebControls.WebParts; using  System.Web.UI.HtmlControls; using  System.ComponentModel; /// <summary>/// OjbData 的摘要说明/// </summary> public   class  OjbData {    public OjbData()    {        //        // TODO: 在此处添加构造函数逻辑        //    }    [DataObjectMethod(DataObjectMethodType.Select, true)]    public DataTable Select()    {        DataTable dt = new DataTable();        dt.Columns.Add("no"typeof(string));        dt.Columns.Add("name"typeof(string));        for (int i = 0; i < 30; i++)        {            DataRow dr = dt.NewRow();            dr[0= "no" + i.ToString().PadLeft(2'0');            dr[1= "name" + i.ToString().PadLeft(2'0');            dt.Rows.Add(dr);        }        return dt;    }}

    Default.aspx

    <% @ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default"  %> <! 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  id ="Head1"  runat ="server" >      < title > SmartGridView测试 </ title > </ head > < body >      < form  id ="form1"  runat ="server" >          < yyc:SmartGridView  ID ="SmartGridView1"  runat ="server"  AutoGenerateColumns ="False"             DataSourceID ="ObjectDataSource1"  Width ="1000px" >              < Columns >                  < asp:BoundField  DataField ="no"  HeaderText ="序号"  SortExpression ="no"   />                  < asp:BoundField  DataField ="name"  HeaderText ="名称"  SortExpression ="name"   />                  < asp:BoundField  DataField ="no"  HeaderText ="序号"  SortExpression ="no"   />                  < asp:BoundField  DataField ="name"  HeaderText ="名称"  SortExpression ="name"   />                  < asp:BoundField  DataField ="no"  HeaderText ="序号"  SortExpression ="no"   />                  < asp:BoundField  DataField ="name"  HeaderText ="名称"  SortExpression ="name"   />                  < asp:BoundField  DataField ="no"  HeaderText ="序号"  SortExpression ="no"   />                  < asp:BoundField  DataField ="name"  HeaderText ="名称"  SortExpression ="name"   />                  < asp:BoundField  DataField ="no"  HeaderText ="序号"  SortExpression ="no"   />                  < asp:BoundField  DataField ="name"  HeaderText ="名称"  SortExpression ="name"   />              </ Columns >              < FixRowCol  FixColumnIndices ="0,1"  FixRowIndices ="0"  IsFixHeader ="True"  TableHeight ="300px"                 TableWidth ="300px"  EnableScrollState ="true"   />          </ yyc:SmartGridView >          < asp:ObjectDataSource  ID ="ObjectDataSource1"  runat ="server"  SelectMethod ="Select"             TypeName ="OjbData" ></ asp:ObjectDataSource >      </ form > </ body > </ html >

    最新回复(0)