转gridview的扩展,实现固定列和列头固定。

介绍
扩展GridView控件:
固定指定行、指定列,根据RowType固定行,根据RowState固定行

使用方法(设置FixRowColumn复合属性):
FixRowType - 需要固定的行的RowType(用逗号“,”分隔)
FixRowState - 需要固定的行的RowState(用逗号“,”分隔)
FixRows - 需要固定的行的索引(用逗号“,”分隔)
FixColumns - 需要固定的列的索引(用逗号“,”分隔)
TableWidth - 表格的宽度
TableHeight - 表格的高度


关键代码
css
/**/ /*固定行*/
.yy_sgv_fixRow
{} {
    position
: relative; top: expression(this.offsetParent.scrollTop - 1);
}

/**/ /*固定列*/
.yy_sgv_fixCol
{} {
    position
: relative; left: expression(this.offsetParent.scrollLeft - 1);
}

/**/ /*高优先级的固定*/
.yy_sgv_fixHigh
{} {
    z-index
: 9999;
}

/**/ /*低优先级的固定*/
.yy_sgv_fixLow
{} {
    z-index
: 1000;
}

c#
using  System;
using  System.Collections.Generic;
using  System.Text;

using  System.Web.UI.WebControls;
using  System.Web.UI;

namespace  YYControls.SmartGridViewFunction
{
    
/**//// <summary>
    
/// 扩展功能:固定指定行、指定列
    
/// </summary>

    public class FixRowColumnFunction : ExtendFunction
    
{
        
/**//// <summary>
        
/// 构造函数
        
/// </summary>

        public FixRowColumnFunction()
            : 
base()
        
{

        }


        
/**//// <summary>
        
/// 构造函数
        
/// </summary>
        
/// <param name="sgv">SmartGridView对象</param>

        public FixRowColumnFunction(SmartGridView sgv)
            : 
base(sgv)
        
{

        }


        
/**//// <summary>
        
/// 扩展功能的实现
        
/// </summary>

        protected override void Execute()
        
{
            
this._sgv.RowDataBoundCell += new SmartGridView.RowDataBoundCellHandler(_sgv_RowDataBoundCell);
            
this._sgv.RenderBegin += new SmartGridView.RenderBeginHandler(_sgv_RenderBegin);
            
this._sgv.RenderEnd += new SmartGridView.RenderEndHandler(_sgv_RenderEnd);
        }


        
/**//// <summary>
        
/// SmartGridView的RowDataBoundCell事件
        
/// </summary>
        
/// <param name="sender"></param>
        
/// <param name="gvtc"></param>

        void _sgv_RowDataBoundCell(object sender, GridViewTableCell gvtc)
        
{
            TableCell tc 
= gvtc.TableCell;
            GridViewRow gvr 
= (GridViewRow)tc.Parent;

            
int i = 0// 0-既不固定行也不固定列;1-固定行或固定列;2-既固定行也固定列
            
// 固定行
            if 
            (
                (
                    
!String.IsNullOrEmpty(this._sgv.FixRowColumn.FixRows) 
                    
&& 
                    Array.Exists(
this._sgv.FixRowColumn.FixRows.Split(','), delegate(string s) return s == gvr.RowIndex.ToString(); })
                )
                
|| 
                (
                    
!String.IsNullOrEmpty(this._sgv.FixRowColumn.FixRowType) 
                    
&& 
                    Array.Exists(
this._sgv.FixRowColumn.FixRowType.Split(','), delegate(string s) return s == gvr.RowType.ToString(); })
                )
                
|| 
                (
                    
!String.IsNullOrEmpty(this._sgv.FixRowColumn.FixRowState) 
                    
&& 
                    Array.Exists(
this._sgv.FixRowColumn.FixRowState.Split(','), delegate(string s) return s == gvr.RowState.ToString(); })
                )
            )
            
{
                i
++;
                Helper.Common.SetAttribute(tc, 
"class""yy_sgv_fixRow", AttributeValuePosition.Last, ' ');
            }

            
// 固定列
            if 
                (
                    
!String.IsNullOrEmpty(this._sgv.FixRowColumn.FixColumns)
                    
&&
                    Array.Exists(
this._sgv.FixRowColumn.FixColumns.Split(','), delegate(string s) return s == gvtc.ColumnIndex.ToString(); })
                )
            
{
                i
++;
                Helper.Common.SetAttribute(tc, 
"class""yy_sgv_fixCol", AttributeValuePosition.Last, ' ');
            }


            
// 低等级的z-index
            if (i == 1)
            
{
                Helper.Common.SetAttribute(tc, 
"class""yy_sgv_fixLow", AttributeValuePosition.Last, ' ');
            }

            
// 高等级的z-index
            else if (i == 2)
            
{
                Helper.Common.SetAttribute(tc, 
"class""yy_sgv_fixHigh", AttributeValuePosition.Last, ' ');
            }

        }


        
/**//// <summary>
        
/// RenderBegin
        
/// </summary>
        
/// <param name="sender"></param>
        
/// <param name="writer"></param>

        void _sgv_RenderBegin(object sender, HtmlTextWriter writer)
        
{
            writer.AddStyleAttribute(HtmlTextWriterStyle.Overflow, 
"auto");
            writer.AddStyleAttribute(HtmlTextWriterStyle.Position, 
"relative");
            writer.AddStyleAttribute(HtmlTextWriterStyle.Width, String.IsNullOrEmpty(
this._sgv.FixRowColumn.TableWidth) ? "100%" : this._sgv.FixRowColumn.TableWidth);
            writer.AddStyleAttribute(HtmlTextWriterStyle.Height, String.IsNullOrEmpty(
this._sgv.FixRowColumn.TableHeight) ? "100%" : this._sgv.FixRowColumn.TableHeight);
            writer.RenderBeginTag(HtmlTextWriterTag.Div);
        }


        
/**//// <summary>
        
/// RenderEnd
        
/// </summary>
        
/// <param name="sender"></param>
        
/// <param name="writer"></param>

        void _sgv_RenderEnd(object sender, HtmlTextWriter writer)
        
{
            writer.RenderEndTag();
        }

    }

}

/* 正式版的实现 结束 */


/* 测试版的实现 开始 */

介绍
平时使用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 >

转载于:https://www.cnblogs.com/terry918/archive/2008/07/01/1233236.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值