Creating a DataGrid that auto-scrolls
I participate on the [aspnet-datadisplaycontrols] list (sign up here).
One of the frequently mentioned gripes (FMG) about the DataGrid control is that it does not automatically scroll
the user to a row when the row is put into "edit" mode (i.e. the edit link of an EditCommandColumn is clicked). So, I thought I would
see if I could come up with a solution so end users around the world would not have to work so hard to edit a record in a long DataGrid.
I want to say one thing before I begin...it should be very rare that anyone has this problem because no on should be returning 100s of rows
to a user. 99.9% of the time the user will not look at even a quarter of the rows returned (if you return 100s of rows). So, my advice
too many of you that are having problems with scrolling, etc. is to build a better drill down interface. That said, there are times
(users running at really low resolution, large text, etc.) where even 30 rows scrolls off the screen. I will now step off my soapbox.
Ok, let's look at the HTML/ASPX markup in our .aspx file (below).
<html>
..... Extraneous code removed .....
<asp:DataGrid id=DataGrid1 runat="server">
<Columns>
<asp:EditCommandColumn ButtonType="LinkButton"
UpdateText="Update"
CancelText="Cancel"
EditText="Edit">
</asp:EditCommandColumn>
</Columns>
</asp:DataGrid>
..... Extraneous code removed .....
</html>
As you can see, there isn't much to dissect in the HTML/ASPX code (above). We have a standard DataGrid with an EditCommandColumn. The AutoGenerateColumns property
is 'true' by default so the underlying data source will supply us with the rest of the columns in the DataGrid. I included
this code here just show that there is nothing special going on in the .aspx file. Lets turn to the code in the code behind file (don't understand code behind - check out Steve Smith's
article).
We will look at the two pieces of code that make the DataGrid auto-scroll. The first bit of code (below) is the Page_Load event.
Private Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) _
Handles MyBase.Load
If Not Page.IsPostBack Then
'Only fill and bind the grid in the Page_Load event
'CreateDataSource programmatically creates a DataTable
DataGrid1.DataSource = CreateDataSource()
DataGrid1.DataBind()
Else
Dim startUpScript As String
startUpScript = "<script language=Javascript>location.href='#" _
& Request.Form("__EVENTTARGET") & "';</script>"
Me.RegisterStartupScript(Me.UniqueID & "StartUp", startUpScript)
End If
End Sub
When the page first loads (Page.IsPostBack equals false), we want to fill the DataGrid with data and call the DataGrid's 'DataBind' method.
If the page has been posted back to the server (i.e. the 'Edit', 'Update', or 'Cancel link is clicked), we want to emit some client-side
script at the bottom of the page. The client-side script needs to be emitted at the bottom of the page so that it is executed after
all of the controls have been emitted to the page.
The System.Web.UI.Page class contains a method called RegisterStartupScript for
doing just that; emitting client-side script to be executed after the page loads. The RegisterStartupScript method takes two
parameters - a 'key' of type string and a 'script' of type string. The key is a unique identifier that allows the Page to ensure
that our script is only emitted to the page once. I usually only register one string of start up script so I use the UniqueID property
of the Page class and concatenate it with the text 'StartUp'.
The 'script' parameter, as you probably could guess, is what is emitted to the page. In our case, we want to execute some
Javascript that will send the user to a particular location on the page. We will make use of a named anchor tag (you will see how the
anchor tag is created and emitted to the page later in the article) to achieve this functionality. The ASP.NET postback mechanism
makes use of Javascript and anytime a postback capable control is emitted to the page, so is the Javascript to make the postback "Work".
Here is the postback Javascript emitted by the ASP.NET postback mechanism:
<script language="javascript">
<!--
function __doPostBack(eventTarget, eventArgument) {
var theform = document.Form1;
theform.__EVENTTARGET.value = eventTarget;
theform.__EVENTARGUMENT.value = eventArgument;
theform.submit();
}
// -->
</script>
Looking at the Javascript, we can see that there is a single function (__doPostBack) that takes two arguments. The first argument
(eventTarget) is the UniqueID if the control that caused the post back. The second argument (eventArgument) is
an object that may contain additional values specific to the postback. Looking back at the code in the Page_Load event (shown
a little earlier in the article), we can see that the code access the __EVENTTARGET element of the Request.Form collection.
As mentioned earlier, the __EVENTTARGET element contains the UniqueID of the control that caused the post back to
the server. We will use the UniqueID to name the anchor tag for each row in the DataGrid. Let's take a look at how we add name an anchor
tag for each row in the DataGrid.
Private Sub DataGrid1_ItemDataBound(ByVal sender As Object, ByVal e As DataGridItemEventArgs) _
Handles DataGrid1.ItemDataBound
Select Case e.Item.ItemType
Case ListItemType.Item, ListItemType.AlternatingItem
Dim editButton As LinkButton = New LinkButton()
editButton = CType(e.Item.Cells(0).Controls(0), LinkButton)
editButton.Attributes.Add("name", "#" & editButton.UniqueID)
Case ListItemType.EditItem
Dim UpdateButton As LinkButton = New LinkButton()
UpdateButton = CType(e.Item.Cells(0).Controls(0), LinkButton)
UpdateButton.Attributes.Add("name", "#" & UpdateButton.UniqueID)
End Select
End Sub
In our example, we don't have to create the anchor tag because our EditCommandColumn is using the LinkButton button type. If we were using
the PushButton button type then we would need to actually add an anchor tag to each row. So, the EditCommandColumn is creating
the anchor tag for us but we still need to add a name to the anchor tag so that our Javascript can send the page to it. To add the name
attribute to the anchor tag for each row, we need to participate in the ItemDataBound event of the DataGrid. In the ItemDataBound event,
we examine the ItemType property of each item. If the ItemType is of the type Item or AlternatingItem then
we will add an attribute (name) with a value of "#" concatenated to the UniqueID of the 'Edit' LinkButton. If the
ItemType is of the type EditItem then we will add an attribute (name) with a value of "#" concatenated to the
UniqueID of the 'Update' LinkButton.
Click here to see a live example!
Click here to see all of the code!
Hopefully, you have found this article helpful. If you have comments, suggestions, etc. then feel free to contact me via this
page.
We have many great DataGrid article here at AspAlliance.com. Click
here to read them.
|