help.net


Musing on .Net

News





hit counters




Open source CMS


Technorati

My blog

Irish blogs

Locations of visitors to this page Get Chitika eMiniMalls

.Net useful

Blogs I read

PocketPC

SQL

Usability

Much better scrolling with Datagrid

I am not happy with the usual scrolling tip you can find everywhere about Datagrids.

Why ? Because you have an external scrolling, so when you scroll, you lost the headings :-(

As you can see in this example, if I have a long list I lost the header.

Most of the solutions are based on the duplication of the Header to a Table on top of the Datagrid.
It's not really good, because you lost the flexibility of the Datagrid attributes and styles.


After a long search, I finally found an answer.. from MSDN ;-)

I adapt this to the Datagrid, and it's working perfectly as you can see in this screenshot of my CMS !

The things to know is you need an .htc file, so obviously this solution is for IE only.
But if you are building an Intranet or an admin page, this is really neat.

The main table created with Datagrid has a stylesheet embedding with the call to this htc code.

Scroll.htc

<PUBLIC:ATTACH event="ondocumentready" handler="onDocumentReady" />
<SCRIPT language="JScript">
function onDocumentReady()
{
   // Create elements
   var tblHeader = this.cloneNode(false);
   var tblBody   = this.cloneNode(false);
   var divCntr   = document.createElement("DIV");

   // Get column widths
   var rgWidths = new Array();
   for (var i = 0; i < this.rows[0].cells.length; i++)
   {
      rgWidths[i] = this.rows[0].cells[i].offsetWidth;
   }

   // Add header row
   var tbdyHeader = document.createElement("TBODY");
   tblHeader.appendChild(tbdyHeader);
   tbdyHeader.appendChild(this.rows[0].cloneNode(true));

   // Add body rows
   var tbdyBody = document.createElement("TBODY");
   tblBody.appendChild(tbdyBody);
  
   for (var i = 1; i < this.rows.length; i++)
   {
      var oRow = this.rows[i].cloneNode(true);
      tbdyBody.appendChild(oRow);
   }

   // Set up body container
   divCntr.style.overflow = "auto";
   if (this.bodyHeight) divCntr.style.height = this.bodyHeight;
   divCntr.appendChild(tblBody);

   // Change existing table
   for (var i = this.rows.length; i > 0; i--)
   {
      this.rows[i-1].removeNode(true);
   }
   var tr1 = this.insertRow();
   var td1 = tr1.insertCell();
   var tr2 = this.insertRow();
   var td2 = tr2.insertCell();
  
   td1.appendChild(tblHeader);
   td2.appendChild(divCntr);

   // Set column widths of all but the last column
   for (var i = 0; i < rgWidths.length - 1; i++)
   {
      tblHeader.rows[0].cells[i].width = rgWidths[i];  
      tblBody.rows[0].cells[i].width   = rgWidths[i];
   }

   tblHeader.style.fontSize    = "100%";
   tblHeader.width             = "100%";
   tblHeader.style.tableLayout = "fixed";
   tblHeader.className         = this.headerCSS ? this.headerCSS : "";
   tblHeader.border = 0;

   tblBody.style.fontSize      = "100%";
   tblBody.width               = "100%";
   tblBody.style.tableLayout   = "fixed";
   tblBody.className           = this.bodyCSS ? this.bodyCSS : "";
   tblBody.border = 0;

   this.cellSpacing = 0;
   this.cellPadding = 0;
}
</SCRIPT>

In the ASP.Net page, where you implement your Datagrid, you need to have the styles below in the <Head> section (eventually you can link to an external stylesheet):

<STYLE>
.tblMain
{
   behavior:url(scroll.htc);
   background-color: highlight;
   border: 1px solid darkblue;
   font-family: Verdana;
   font-size: .8em;
}
.tblHeader
{
   color: highlighttext;
}
.tblBody
{
   background-color: #EEEEEE;
   color: darkblue;
}
</STYLE>

And finally the Datagrid object (in red and bold the specific parts). This example is the code for the Datagrid shown in the screenshot above :

<asp:datagrid bodyHeight="100" bodyCSS="tblBody" headerCSS="tblHeader"
   cssclass="tblMain" id="DGVersions" Runat="server"  AutoGenerateColumns="false" Font-Size="8"
         HeaderStyle-Font-Bold="True" HeaderStyle-HorizontalAlign="Center" Width="280">
         <AlternatingItemStyle CssClass="Alt" />
         <Columns>
          <asp:BoundColumn DataField="SectionVersion" HeaderText="Version" HeaderStyle-Width=100 ItemStyle-Width="100"  ItemStyle-HorizontalAlign=center/>
          <asp:BoundColumn DataField="DateCreation" headertext="Created"  HeaderStyle-HorizontalAlign=Center HeaderStyle-Width=100 ItemStyle-Width="100"  />
          <asp:TemplateColumn ItemStyle-Width=50>
           <ItemTemplate>
            <asp:ImageButton ID="ButDelVersion" Runat="server" ImageUrl="~/images/delete.gif" CommandName="Delete" />
            <asp:ImageButton ID="ButEditVersion" Runat="server" imageurl="~/images/edit.gif" CommandName="Edit" />
           </ItemTemplate>
          </asp:TemplateColumn>
         </Columns>
        </asp:datagrid>


This is indeed a first version, and I have to fix some stuff like:

- Alternative colors for the datagrid rows
- Writing a Javascript equivalent code to make the scroll working with other browsers.

I hope also that this scroll idea will be part of ASP.Net 2.0 natively ;-)

 

Posted: Sep 10 2003, 11:26 AM by help.net | with 14 comment(s)
Filed under:

Comments

TrackBack said:

# September 10, 2003 7:03 AM

TrackBack said:

# September 13, 2003 6:58 PM

Tosh Meston said:

So, I am reading your blog, looking at this javascript and thinking something about this looks familiar... when I realize it's mine. Heh, I wrote that htc in that Web Team Talking article. You know, you somebody else posted a really simple html/css solution to this for IE in the comments of the article, which I think I like better than this one.


http://msdn.microsoft.com/library/en-us/dnwebteam/html/webteam11042002.asp?frame=true#Webteam11042002_topic2
# September 14, 2003 6:25 AM

Raman Kohli said:

Hi there ...

That is really the great stuff.Actually can you please tell me is it possible to freeze the column in the datagrid the way we can do the freezing in the Excel sheet.

Please give me the guidelines for this. Thanks in advance.

Regards
Raman Kohli
Raman.Kohli@lntinfotech.com
# November 13, 2003 2:52 PM

manmohan said:

heh Raman, any luck with freezing columns in the datagrid
# December 8, 2003 5:26 PM

Paschal said:

Infragistics does that in their components(not for free).
# December 8, 2003 5:36 PM

mahmoud said:

please tell me how i can make horizontal scrolling with the same script
# March 6, 2004 1:40 PM

Yumna said:

Yes, please tell us how to have fixed horizontal scrolling.
# March 15, 2004 8:24 AM

pllms said:

Hi, I tried and I manage to have the Header of the datagrid freeze.

But when the Datagrid is in the edit mode, it does not capture the Default value for the Drop Drop list box.

Is there a solution?

Regards,
pllms


# March 18, 2004 4:33 AM

LARa said:

It works in my station where i devlope, but in client browser i get error. the client's browser version in 6.0 :(
# April 12, 2004 3:06 AM

Bryant Likes said:

This is great! Thanks for the tip, I'm using it on an intranet site I'm building.

It is very easy to add alternating colors for rows. Just add in AlternatingItemStyle-BackColor="#eeeeee" in the asp:DataGrid element.

Now to figure out how to allow items to be moved up and down in the list...
# May 21, 2004 8:43 PM

MacGeg said:

Hi,
I would have a datagrid that scrolls only the contents but not the pager; is possible to freeze also the pager? Thanks,

Regards,
# May 30, 2004 10:50 AM

e$ said:

For those interested, I've written a scrolling DataGrid.

http://www.popularword.com/

http://www.cronometric.com/popularword/scroll.aspx

This control is an extension of MS' DataGrid. It supports a scroll_mode of horizontal, vertical, both, and none.
# June 16, 2004 12:31 PM

Pradhan said:

http://www.popularword.com/

is giving errors. The error is
Server Error in '/popularword' Application.
--------------------------------------------------------------------------------

Method not found: System.Drawing.Color System.Web.UI.WebControls.Style.get_BackColor().
# August 4, 2004 1:07 PM