有滚动条、固定Header的ASP.Net DataGrid实现-阿里云开发者社区

开发者社区> 开发与运维> 正文

有滚动条、固定Header的ASP.Net DataGrid实现

简介: 客户要一个有滚动条的ASP.Net DataGrid控件,只好写了: ");> using  System; using  System.

客户要一个有滚动条的ASP.Net DataGrid控件,只好写了:

");>
using  System;

using  System.Web.UI;

using  System.Web.UI.WebControls;

using  System.ComponentModel;

using  System.Diagnostics;

using  System.IO;

using  System.Web.UI.Design.WebControls;

using  System.Text;

using  System.Drawing;

 

[assembly:TagPrefix(
" Microsoft.Gtec.Dsv " " gtecdsv " )]

namespace  Microsoft.Gtec.Dsv

{

  
///   <summary>

  
///  Summary description for WebCustomControl1.

  
///   </summary>

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

  
public   class   ScrollableFixedHeaderDataGrid: System.Web.UI.WebControls.DataGrid

  {

    
protected   override   void  Render(HtmlTextWriter output)

    {

      
// Use this flag to determine whether the component is in design-time or runtime.

      
// The control will be rendered differently in IDE.

      
// Don't bother to use DataGridDesigner.GetDesignTimeHtml

      
bool  designMode  =  ((Site  !=   null &&  (Site.DesignMode));

      
// Backing up the properties need to change during the render process

      
string  tempLeft  =  Style[ " LEFT " ];

      
string  tempTop  =  Style[ " TOP " ];

      Unit tempHeight 
=  Height;

      
string  tempTableStyle  =  Style[ " TABLE-LAYOUT " ];

 

      
// Render a "<div>" container with scrollbars.

      output.WriteBeginTag(
" div " );

      output.WriteAttribute(
" id " ,ID  +   " _div " );

      output.WriteAttribute(
" style " ,

        
" HEIGHT:  "   +  Height  +   " ; "   +

        
// Leave 20px for the vertical scroll bar,

        
// assuming the end-user will not set his scroll bar to more than 20px.

        
" WIDTH:  "   +  (Width.Value  +   20 +   " px; "   +

        
" TOP:  "   +  Style[ " TOP " +   " ; "   +

        
" LEFT:  "   +  Style[ " LEFT " +   " ; "   +

        
" POSITION:  "   +  Style[ " POSITION " +   " ; "   +

        
" OVERFLOW-X: auto; "   +

        
" Z-INDEX:  "   +  Style[ " Z-INDEX " +   " ; "   +

        
// Render the scrollbar differently for design-time and runtime.

        
" OVERFLOW-Y:  "   +  (designMode ? " scroll " : " auto " )

        );

      output.Write(HtmlTextWriter.TagRightChar);

                       

      
// The DataGrid is inside the "<div>" element, so place it at (0,0).

      Style[
" LEFT " =   " 0px " ;

      Style[
" TOP " =   " 0px " ;

      
// Render the DataGrid.

      
base .Render(output);

      output.WriteEndTag(
" div " );

      
// Restore the values

      Style[
" LEFT " =  tempLeft;

      Style[
" TOP " =  tempTop;

 

      
// The following rendering is only necessary under runtime. It has negative impact during design time.

      
if  ( ! designMode)

      {

        
// Render another copy of the DataGrid with only headers.

        
// Render it after the DataGrid with contents,

        
// so that it is on the top. Z-INDEX is more complex here.

        
// Set Height to 0, so that it will adjust on its own.

        Height 
=   new  Unit( " 0px " );

        StringWriter sw 
=   new  StringWriter();

        HtmlTextWriter htw 
=   new  HtmlTextWriter(sw);

        
// This style is important for matching column widths later.

        Style[
" TABLE-LAYOUT " =   " fixed " ;

        
base .Render(htw);

        StringBuilder sbRenderedTable 
=  sw.GetStringBuilder();

        htw.Close();

        sw.Close();

        Debug.Assert((sbRenderedTable.Length 
>   0 ),

          
" Rendered HTML string is empty. Check viewstate usage and databinding. " );

        
string  temp  =  sbRenderedTable.ToString();

        
if  (sbRenderedTable.Length  >   0 )

        {

          
// AllowPaging at the top?

          
if  ((AllowPaging)  &&  ((PagerPosition.Top  ==  PagerStyle.Position  ||  (PagerPosition.TopAndBottom  ==  PagerStyle.Position))))

          {

            Trace.WriteLine(temp);

            sbRenderedTable.Replace(ID,ID 
+   " _Pager " 0 , (temp.IndexOf(ID)  +  ID.Length));

            temp 
=  sbRenderedTable.ToString();

            
string  pager  =  temp.Substring( 0 , temp.ToLower().IndexOf( @" </tr> " +   5 );

            Trace.WriteLine(pager);

            output.Write(pager);

            output.WriteEndTag(
" table " );

            
// Start of pager's <tr>

            
int  start  =  temp.ToLower().IndexOf( @" <tr " );

            
// End of pager's </tr>

            
int  end  =  temp.ToLower().IndexOf( @" </tr> " +   5 ;

            
// Remove the <tr> for pager from the string. Prepare to render the headers.

            sbRenderedTable.Remove(start,end
- start);

            Trace.WriteLine(sbRenderedTable.ToString());

            sbRenderedTable.Replace(ID 
+   " _Pager " ,ID  +   " _Headers " 0 , (temp.IndexOf(ID + " _Pager " +  (ID + " _Pager " ).Length));

            temp 
=  sbRenderedTable.ToString();

            
string  tableHeaders  =  temp.Substring( 0 , (temp.ToLower()).IndexOf( @" </tr> " +   5 );

            Trace.WriteLine(tableHeaders);

            output.Write(tableHeaders);

            output.WriteEndTag(
" table " );

            
string  headerID  =  ID  +   " _Headers " ;

            
string  pagerID  =  ID  +   " _Pager " ;

            
string  divID  =  ID  +   " _div " ;

            
string  adjustWidthScript  =   @"

                                                <script language=javascript>

                                                        //debugger;

                                                        var headerTableRow = 
"   +  headerID  +   @" .rows[0];

                                                        var originalTableRow = 
"   +  ID  +   @" .rows[1]; "

              
// Adjust header row's height.

              
+   @"

                                                        headerTableRow.height = originalTableRow.offsetHeight;

                                                        
"   +

              
// Adjust pager row's height, width.

              pagerID 
+   @" .rows[0].height =  "   +  ID  +   @" .rows[0].offsetHeight;

                                                        
"   +

              pagerID 
+   @" .style.width =  "   +  ID  +   @" .offsetWidth;

                                                        for (var i = 0; i < headerTableRow.cells.length; i++) {

                                                                headerTableRow.cells[i].width = originalTableRow.cells[i].offsetWidth;

                                                        }

                                                        
"   +

              
// Also needs to adjust the width of the "<div>" at client side in addition to servier side,

              
// since the Table's actual width can go beyond the width specified at server side under Edit mode.

              
// The server side width manipulation is mainly for design-time appearance.

              divID 
+   @" .style.width =  "   +  ID  +   @" .offsetWidth + 20 + 'px';

                                                                
"   +

              
// The following script is for flow-layout. We cannot get the position of the control

              
// on server side if the the page is with flow-layout.

              headerID 
+   @" .style.left =  "   +  divID  +   @" .offsetLeft;

                                                                
"   +

              headerID 
+   @" .style.top =  "   +  divID  +   @" .offsetTop +  "   +  pagerID  +   @" .offsetHeight;

                                                                
"   +

              headerID 
+   @" .style.position = 'absolute';

                                                                
"   +

              pagerID 
+   @" .style.left =  "   +  divID  +   @" .offsetLeft;

                                                                
"   +

              pagerID 
+   @" .style.top =  "   +  divID  +   @" .offsetTop;

                                                                
"   +

              pagerID 
+   @" .style.position = 'absolute';

                                                </script>
" ;

            Page.RegisterStartupScript(
" dummyKey "   +   this .ID, adjustWidthScript);

            
// output.Write(adjustWidthScript);

          }

          
else

          {

            
// Replace the table's ID with a new ID.

            
// It is tricky that we must only replace the 1st occurence,

            
// since the rest occurences can be used for postback scripts for sorting.

            sbRenderedTable.Replace(ID,ID 
+   " _Headers " 0 , (temp.IndexOf(ID)  +  ID.Length));

            Trace.WriteLine(sbRenderedTable.ToString());

            
// We only need the headers, stripping the rest contents.

            temp 
=  sbRenderedTable.ToString();

            
string  tableHeaders  =  temp.Substring( 0 , (temp.ToLower()).IndexOf( @" </tr> " +   5 );

            Trace.WriteLine(tableHeaders);

            output.Write(tableHeaders);

            output.WriteEndTag(
" table " );

            
// Client side script for matching column widths.

            
// Can't find a way to do this on the server side, since the browser can change widths on the client side.

            
string  adjustWidthScript  =   @"

                                                <script language=javascript>

                                                        //debugger;

                                                        var headerTableRow = 
"   +   this .ID  +   @" _Headers.rows[0];

                                                        var originalTableRow = 
"   +   this .ID  +   @" .rows[0];

                                                        headerTableRow.height = originalTableRow.offsetHeight;

                                                        for (var i = 0; i < headerTableRow.cells.length; i++) {

                                                                headerTableRow.cells[i].width = originalTableRow.cells[i].offsetWidth;

                                                        }

                                                        
"   +

              
// Also needs to adjust the width of the "<div>" at client side in addition to servier side,

              
// since the Table's actual width can go beyond the width specified at server side under Edit mode.

              
// The server side width manipulation is mainly for design-time appearance.

              
this .ID  +   " _div "   +   @" .style.width =  "   +   this .ID  +   @" .offsetWidth + 20 + 'px';

                                                                
"   +

              
// The following script is for flow-layout. We cannot get the position of the control

              
// on server side if the the page is with flow-layout.

              
this .ID  +   " _Headers "   +   @" .style.left =  "   +   this .ID  +   @" _div.offsetLeft;

                                                                
"   +

              
this .ID  +   " _Headers "   +   @" .style.top =  "   +   this .ID  +   @" _div.offsetTop;

                                                                
"   +

              
this .ID  +   " _Headers "   +   @" .style.position = 'absolute';

                                                </script>
" ;

            Page.RegisterStartupScript(
" dummyKey "   +   this .ID, adjustWidthScript);

            
// output.Write(adjustWidthScript);

          }

          Height 
=  tempHeight;

          Style[
" TABLE-LAYOUT " =  tempTableStyle;

        }

      }

    }

               

    
protected   override   void  OnInit(EventArgs e)

    {

      
if  ( 0   ==  Width.Value) Width  =   new  Unit( " 400px " );

      
if  ( 0   ==  Height.Value) Height  =   new  Unit( " 200px " );

      
// Transparent header is not allowed.

      
if  (HeaderStyle.BackColor.IsEmpty)

      {

        HeaderStyle.BackColor 
=  Color.White;

      }

      
// Transparent pager is not allowed.

      
if  (PagerStyle.BackColor.IsEmpty)

      {

        PagerStyle.BackColor 
=  Color.White;

      }

 

      
base .OnInit (e);

    }

 

    [Browsable(
false )]

    
public   override   bool  ShowHeader

    {

      
get

      {

        
return   true ;

      }

      
set

      {

        
if  ( false   ==  value)

          
throw   new  InvalidOperationException( " Use the original DataGrid to set ShowHeaders to false. " );

      }

    }

  }

}

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

分享:
开发与运维
使用钉钉扫一扫加入圈子
+ 订阅

集结各类场景实战经验,助你开发运维畅行无忧

其他文章