Datagrid postback issue

R

RRB

Hello,

I have a postback issue concerning the Datagrid. I posted this problem
to several forums before and didn’t receive a single response from
anyone. I initially thought my issue was related to sorting but now
understand it as a larger issue. Here goes:

I have a Datagrid that for various business reasons has the following
relevant characteristics:

- It does not keep viewstate
- It has template columns, manually generated
- it supports in-place editing (which cells are editable varies by
row-type).
- it supports column sorting by clickable column headers.

It is in implementing the column-sorting that I ran into trouble. From
what I have determined, once you databind the datagrid upon postback,
the datagrid becomes immutable from postback event handlers.

The normal flow is as follows:

Upon postback I manually add my columns, then set my grid datasource to
a session-cached DataView. Next, I call DataBind() on my grid.

Next, the column header’s click event fires and in the event handler, I
determine the sort order and set the sort property of my dataview.
Finally, I call DataBind() on the grid again.

Result: The grid displays as if I had not clicked a column header. And
if I click another column header, I will then see the grid sorted by the
column I’d previously clicked. The apparent behavior is that that the
grid is ignoring the second databind, as no exception is being thrown.

===========================

Test 1:

1. Upon postback, I manually add my columns, then set my grid datasource
to a session-cached DataView. Next, I call DataBind() on my grid.

1A. Next, I set the grid datasource to a simple string array, and call
DataBind() on the grid again.

2. Next, the column header’s click event fires and in the event handler,
I determine the sort order and set the sort property of my dataview.
Finally, I call DataBind() on the grid again.

Result: The grid displays empty rows (once for each string in my string
array) since my data didn’t match my columns. Thus my second databind
was successful.

===========================

Test 2:

1. Upon postback, I manually add my columns, then set my grid datasource
to a session-cached DataView. Next, I call DataBind() on my grid.

2. Next, the column header’s click event fires.

2A. In the event handler, I set the grid datasource to a simple string
array, and call DataBind() on the grid again. All other code is
commented out.

Result: The grid displays as if I had not clicked a column header. And
if I click another column header, I will then see the grid sorted by the
column I’d previously clicked. My second databind was NOT successful.

===========================

All I have changed between Test 1 and Test 2 is where I do the second
databind. In Test 1, I perform it in Page_Load before the click event is
fired. In Test 2, I perform it afterward in the click event handler.

Any insight on this issue would be of immense help! Thank you in
advance.
 
S

Scott M.

You should not be databinding your grid in the Page_Load postback section
only in the Not Postback section of Page_Load. On all postbacks, you should
be calling databind from the event handler that caused the postback (so
databinding should be the last thing you do in your SortCommand event
handler as well as your UpdateCommand, EditCommand, PageIndexChanged, etc.

Also, since you have viewstate turned off for the grid, you must realize
that you will have to persist the state information of the grid yourself
(this is not just the data that the grid was holding, but the current sort
criteria, the selected item, the current page index, etc.
 
R

RRB

Hi Scott, and thanks for your reply.

Unfortunately, because I am not maintaining Viewstate for the datagrid,
the DataBind() call in the Page_Load() method upon postback is necessary
in order for the events to fire. I'll post relevant documentation on
that to the thread.

I'm currently maintaining the EditItem index property but nothing else,
so I'll take a look down that avenue. Again, thank you.
 
S

Scott M.

I wouldn't handle it that way. As I stated, with ViewState turned off, you
have to persist the EditItem, SortCriteria, PageIndex, etc. Since you are
tracking these values anyway, you can simply compare the old value against
the new value and call the appropriate event handler yourself. This would
allow you to NOT call DataBind in the Page_Load postback section and instead
call it in the event handler as it should be.
 
R

RRB

Scott,
fair enough. I should say here that I'm new to ASP.Net so I'm certain
I'm doing several things the hard way. Your approach is attractive to me
because it means I'd also halve my processing on the back-end. Articles
I'd come acriss had led me to believe there was no other way to properly
fire the event.

Ok, so now I have a question:

Currently, my event handler is being passed a reference to the column
button that was clicked (ie the sender object). If I bypass the
binding, how would I determine the column clicked? I looked in the
Request object but didn't see anything beyond my having to sleuth
through the parameter name value collection.

Thanks for your help on this, by the way.
 
S

Scott M.

There are several ways to make this work. The simplest is to just turn
ViewState on for the grid, but I'm assuming your data either changes from
minute to minute or you are persisting the data yourself in some other way.

To know which column was clicked (I assume here you are talking about
Select, Delete, Edit, Update, Cancel), you need to test for the event
differently than normal controls. You could follow a sample I have below:

Add the following code to your code-behind (this assumes the checkbox is
named "chkDynamic"):

Protected Sub chkDynamic_CheckedChanged(ByVal Sender As Object, ByVal e As
System.EventArgs)
'This sub will be run for every row that has had its value changed
Dim chk As CheckBox = CType(Sender, CheckBox)
Dim item As DataGridItem = CType(chk.NamingContainer, DataGridItem)
' "item" is now a reference to the DataGrid selected row
If chk.Checked Then item.BackColor = Color.Gray
'From here, you could grab some data from this row with:
item.FindControl("ControlName")
'and then you would know which record was selected.
End Sub
Private Sub dg_ItemCreated(ByVal sender As Object, ByVal e As
System.Web.UI.WebControls.DataGridItemEventArgs) Handles dg.ItemCreated
'This sub runs anytime the DataGrid needs to dynamically create a cotrol
'but we only are interested in rows that may have controls (not header,
footer or pager rows)
If e.Item.ItemType = ListItemType.Item Or e.Item.ItemType =
ListItemType.AlternatingItem Then
Dim chk As CheckBox = CType(e.Item.FindControl("chkDynamic"),
CheckBox)
AddHandler chk.CheckedChanged, AddressOf chkDynamic_CheckedChanged
'This adds a client-side JavaScript event handler.
'You must also have added a client-side JavaScript function called
chkShow(sender)
chk.Attributes.Add("onClick", "chkShow(this," & rowNum.ToString &
")")
End If
End Sub
 
R

RRB

Hi Scott,
Thanks for your helpful replies. I didn't go with your solution but you
pointed me in the right direction and I'm now no longer reliant on
binding my stateless datagrid upon postback.

In a nutshell, I'm setting the eventtarget and eventargument fields on a
button click, then testing for the specific value on postback and
calling my sort method, which sets the sort, then binds the grid.

Works like a charm!

Thanks again.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,819
Latest member
masterdaster

Latest Threads

Top