天天看點

有滾動條、固定Header的ASP.Net DataGrid實作

客戶要一個有滾動條的ASP.Net DataGrid控件,隻好寫了:

");>

using

 System;

 System.Web.UI;

 System.Web.UI.WebControls;

 System.ComponentModel;

 System.Diagnostics;

 System.IO;

 System.Web.UI.Design.WebControls;

 System.Text;

 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

];

 tempTop 

TOP

      Unit tempHeight 

 Height;

 tempTableStyle 

TABLE-LAYOUT

Render a "<div>" container with scrollbars.

      output.WriteBeginTag(

div

);

      output.WriteAttribute(

id

,ID 

+

_div

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: 

LEFT: 

POSITION: 

POSITION

OVERFLOW-X: auto;

Z-INDEX: 

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[

0px

Render the DataGrid.

base

.Render(output);

      output.WriteEndTag(

Restore the values

 tempLeft;

 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(

        StringWriter sw 

 StringWriter();

        HtmlTextWriter htw 

 HtmlTextWriter(sw);

This style is important for matching column widths later.

        Style[

fixed

.Render(htw);

        StringBuilder sbRenderedTable 

 sw.GetStringBuilder();

        htw.Close();

        sw.Close();

        Debug.Assert((sbRenderedTable.Length 

>

),

Rendered HTML string is empty. Check viewstate usage and databinding.

 temp 

 sbRenderedTable.ToString();

 (sbRenderedTable.Length 

        {

AllowPaging at the top?

 ((AllowPaging) 

 ((PagerPosition.Top 

==

 PagerStyle.Position 

||

 (PagerPosition.TopAndBottom 

 PagerStyle.Position))))

          {

            Trace.WriteLine(temp);

            sbRenderedTable.Replace(ID,ID 

_Pager

, (temp.IndexOf(ID) 

 ID.Length));

            temp 

 pager 

 temp.Substring(

, 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>

 end 

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 

_Headers

, (temp.IndexOf(ID

 (ID

).Length));

 tableHeaders 

, (temp.ToLower()).IndexOf(

            Trace.WriteLine(tableHeaders);

            output.Write(tableHeaders);

 headerID 

 ID 

 pagerID 

 divID 

 adjustWidthScript 

                                                <script language=javascript>

                                                        //debugger;

                                                        var headerTableRow = 

.rows[0];

                                                        var originalTableRow = 

.rows[1];

Adjust header row's height.

                                                        headerTableRow.height = originalTableRow.offsetHeight;

Adjust pager row's height, width.

              pagerID 

.rows[0].height = 

.rows[0].offsetHeight;

.style.width = 

.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 

.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 = 

.offsetLeft;

.style.top = 

.offsetTop + 

.offsetHeight;

.style.position = 'absolute';

.offsetTop;

                                                </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.

We only need the headers, stripping the rest contents.

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.

.ID 

_Headers.rows[0];

_div.offsetLeft;

_div.offsetTop;

          Height 

 tempHeight;

          Style[

 tempTableStyle;

        }

      }

    }

 OnInit(EventArgs e)

 Width.Value) Width 

400px

 Height.Value) Height 

200px

Transparent header is not allowed.

 (HeaderStyle.BackColor.IsEmpty)

        HeaderStyle.BackColor 

 Color.White;

Transparent pager is not allowed.

 (PagerStyle.BackColor.IsEmpty)

        PagerStyle.BackColor 

.OnInit (e);

    [Browsable(

false

 ShowHeader

get

return

true

set

 value)

throw

 InvalidOperationException(

Use the original DataGrid to set ShowHeaders to false.

  }

}

繼續閱讀