Computer Magic
Software Design Just For You
 
 



Reduce the size of your data grid viewstate in ASP.NET

This document is property of Computer Magic And Software Design © 2004. It may not be redistributed or reproduced in any form without express written permission from the author.

Keywords: ASP.NET, Datagrid, Webforms, Sorting, Viewstate, Paging, Sort
Direction

Viewstate, a Datagrid and You


Working with the datagrid:

The initial reaction to working with the datagrid is WOW, this thing is
great! As you actually begin to use the thing though it quickly becomes
apparent that there are some limitations – mostly in the form of
inconvenience. The first thing many people notice is the obscene size of the viewstate when the datagrid is populated. Why does this occur? Simple. By default, the viewstate is on for all server side controls. That means all controls in the datagrid such as link buttons have an entry. If you are showing 10 rows with one Remove link per row, do the math, it begins to add up. In addition, each control that makes up the rendered datagrid also has viewstate properties (including the actual table row and table cells).
Think that’s all? Think again. The viewstate is stored in an encoded
format called Base 64. This format by its very nature causes about a 30% increase in data size. Now before you begin criticizing Microsoft for the bloat, you should be aware that the Base 64 encoding is one of the standards in use for transferring binary information in e-mail. E-mail, like HTML, uses a text based protocol. As such, the Base 64 encoding reduces the binary information to a safe and transmittable format. This also makes Base 64 encoded information fit nicely into a hidden input on a web page called __VIEWSTATE. Take a look at the example below.

<input type="hidden" name="__VIEWSTATE" 
value="dDwtMTkyNjUyMzE4Mjt0PDtsPGk8MD47PjtsPHQ8O2w8aTw0Pjs+O2w8dDw7bDxpPDEyPjtpPDEzPjs+O2w8dDw7bDxpPDA+Oz47bDx0PDtsPGk8MTc+O2k8MTk+Oz47bDx0PHA8cDxsPFRleHQ7PjtsPEdvb2QgTW9ybmluZzs+Pjs+Ozs+O3Q8cDxwPGw8VGV4dDs+O2w8cmF5cEBwY2FkbWluLmN0Yy5lZHU7Pj47Pjs7Pjs+Pjs+Pjt0PDtsPGk8Mz47PjtsPHQ8O2w8aTwxPjtpPDM+Oz47bDx0PEAwPHA8cDxsPFZpcnR1YWxJdGVtQ291bnQ7UGFnZUNvdW50O18hSXRlbUNvdW50O18hRGF0YVNvdXJjZUl0ZW1Db3VudDtEYXRhS2V5czs+O2w8aTwxNDAyPjtpPDE0MT47aTwxMD47aTwxNDAyPjtsPD47Pj47PjtAMDxAMDxwPGw8SGVhZGVyVGV4dDs+O2w8aWQ7Pj47Ozs7 PjtAMDxwPGw8SGVhZGVyVGV4dDs+O2w8RXZlbnQ7Pj47Ozs7PjtAMDxwPGw8SGVhZGVyVGV4dDs+O2w8VHlwZTs+Pjs7Ozs+O0AwPHA8bDxIZWFkZXJUZXh0Oz47bDxDYXVzZWQgQnkgVXNlcjs+Pjs7Ozs+O0AwPHA8bDxIZWFkZXJUZXh0Oz47bDxMb2dnZWQgQXQgXDxJTUcgSEVJR0hUPThweCBXSURUSD04cHggQk9SREVSPTAgc3JjPScvYXJ0L2Rvd24ucG5nJyAvXD47Pj47Ozs7PjtAMDxwPGw8SGVhZGVyVGV4dDs+O2w8QWN0aW9uczs+Pjs7Ozs+Oz47Ozs7Ozs7Ozs+O2w8aTwwPjs+O2w8dDw7bDxpPDI+O2k8Mz47aTw0PjtpPDU+O2k8Nj47aTw3PjtpPDg+O2k8OT47aTwxMD47aTwxMT47PjtsPHQ8O2w8aTwwPjtpPDE+O2k8Mj47aTwzPjtpPDQ+O2k8NT47PjtsPHQ8cDx wPGw8VGV4dDs+O2w8NTs+Pjs+Ozs+O3Q8cDxwPGw8VGV4dDs+O2w8RXZlbnQgU3Vic2NyaXB0aW9uIFJlbW92ZWQ7Pj47Pjs7Pjt0PHA8cDxsPFRleHQ7PjtsPFN1Y2Nlc3NBdWRpdDs+Pjs+Ozs+O3Q8cDxwPGw8VGV4dDs+O2w8cmF5cEBwY2FkbWluLmN0Yy5lZHU7Pj47Pjs7Pjt0PHA8cDxsPFRleHQ7PjtsPDgvMTYvMjAwNCAxOjE1OjI4IFBNOz4+Oz47Oz47dDw7bDxpPDE+Oz47bDx0PHA8O3A8bDxvbmNsaWNrO2hyZWY7PjtsPHJldHVybiBjb25maXJtKCdBcmUgeW91IHN1cmUgeW91IHdhbnQgdG8gcmVtb3ZlIHRoaXMgbm90aWZpY2F0aW9uIGl0ZW0/JylcOztqYXZhc2NyaXB0Ol9fZG9Qb3N0QmFjaygnbG5rUmVtb3ZlRXZlbnQnLCc1Jyk7Pj4+Ozs+Oz4+Oz4+O3Q8O2 w8aTwwPjtpPDE+O2k8Mj47aTwzPjtpPDQ+O2k8NT47PjtsPHQ8cDxwPGw8VGV4dDs+O2w8Njs+Pjs+Ozs+O3Q8cDxwPGw8VGV4dDs+O2w8VXNlciBMb2cgT3V0Oz4+Oz47Oz47dDxwPHA8bDxUZXh0Oz47bDxTdWNjZXNzQXVkaXQ7Pj47Pjs7Pjt0PHA8cDxsPFRleHQ7PjtsPHJheXBAcGNhZG1pbi5jdGMuZWR1Oz4+Oz47Oz47dDxwPHA8bDxUZXh0Oz47bDw4LzE2LzIwMDQgMToxNTo0MyBQTTs+Pjs+Ozs+O3Q8O2w8aTwxPjs+O2w8dDxwPDtwPGw8b25jbGljaztocmVmOz47bDxyZXR1cm4gY29uZmlybSgnQXJlIHlvdSBzdXJlIHlvdSB3YW50IHRvIHJlbW92ZSB0aGlzIG5vdGlmaWNhdGlvbiBpdGVtPycpXDs7amF2YXNjcmlwdDpfX2RvUG9zdEJhY2soJ2xua1JlbW92ZUV2Z W50JywnNicpOz4+Pjs7Pjs+Pjs+Pjt0PDtsPGk8MD47aTwxPjtpPDI+O2k8Mz47aTw0PjtpPDU+Oz47bDx0PHA8cDxsPFRleHQ7PjtsPDc7Pj47Pjs7Pjt0PHA8cDxsPFRleHQ7PjtsPFN1Y2Nlc3NmdWxsIExvZ2luOz4+Oz47Oz47dDxwPHA8bDxUZXh0Oz47bDxTdWNjZXNzQXVkaXQ7Pj47Pjs7Pjt0PHA8cDxsPFRleHQ7PjtsPHJheXBAcGNhZG1pbi5jdGMuZWR1Oz4+Oz47Oz47dDxwPHA8bDxUZXh0Oz47bDw4LzE2LzIwMDQgMToxNTo0OSBQTTs+Pjs+Ozs+O3Q8O2w8aTwxPjs+O2w8dDxwPDtwPGw8b25jbGljaztocmVmOz47bDxyZXR1cm4gY29uZmlybSgnQXJlIHlvdSBzdXJlIHlvdSB3YW50IHRvIHJlbW92ZSB0aGlzIG5vdGlmaWNhdGlvbiBpdGVtPycpXDs7amF2YXNj cmlwdDpfX2RvUG9zdEJhY2soJ2xua1JlbW92ZUV2ZW50JywnNycpOz4+Pjs7Pjs+Pjs+Pjt0PDtsPGk8MD47aTwxPjtpPDI+O2k8Mz47aTw0PjtpPDU+Oz47bDx0PHA8cDxsPFRleHQ7PjtsPDg7Pj47Pjs7Pjt0PHA8cDxsPFRleHQ7PjtsPFByb2ZpbGUgSW5mb3JtYXRpb24gU2F2ZWQ7Pj47Pjs7Pjt0PHA8cDxsPFRleHQ7PjtsPFN1Y2Nlc3NBdWRpdDs+Pjs+Ozs+O3Q8cDxwPGw8VGV4dDs+O2w8cmF5cEBwY2FkbWluLmN0Yy5lZHU7Pj47Pjs7Pjt0PHA8cDxsPFRleHQ7PjtsPDgvMTYvMjAwNCAxOjE4OjM5IFBNOz4+Oz47Oz47dDw7bDxpPDE+Oz47bDx0PHA8O3A8bDxvbmNsaWNrO2hyZWY7PjtsPHJldHVybiBjb25maXJtKCdBcmUgeW91IHN1cmUgeW91IHdhbnQgdG8gcmV tb3ZlIHRoaXMgbm90aWZpY2F0aW9uIGl0ZW0/JylcOztqYXZhc2NyaXB0Ol9fZG9Qb3N0QmFjaygnbG5rUmVtb3ZlRXZlbnQnLCc4Jyk7Pj4+Ozs+Oz4+Oz4+O3Q8O2w8aTwwPjtpPDE+O2k8Mj47aTwzPjtpPDQ+O2k8NT47PjtsPHQ8cDxwPGw8VGV4dDs+O2w8OTs+Pjs+Ozs+O3Q8cDxwPGw8VGV4dDs+O2w8UHJvZmlsZSBJbmZvcm1hdGlvbiBTYXZlZDs+Pjs+Ozs+O3Q8cDxwPGw8VGV4dDs+O2w8U3VjY2Vzc0F1ZGl0Oz4+Oz47Oz47dDxwPHA8bDxUZXh0Oz47bDxyYXlwQHBjYWRtaW4uY3RjLmVkdTs+Pjs+Ozs+O3Q8cDxwPGw8VGV4dDs+O2w8OC8xNi8yMDA0IDE6Mjg6MzggUE07Pj47Pjs7Pjt0PDtsPGk8MT47PjtsPHQ8cDw7cDxsPG9uY2xpY2s7aHJlZjs+O2w8cmV0dX JuIGNvbmZpcm0oJ0FyZSB5b3Ugc3VyZSB5b3Ugd2FudCB0byByZW1vdmUgdGhpcyBub3RpZmljYXRpb24gaXRlbT8nKVw7O2phdmFzY3JpcHQ6X19kb1Bvc3RCYWNrKCdsbmtSZW1vdmVFdmVudCcsJzknKTs+Pj47Oz47Pj47Pj47dDw7bDxpPDA+O2k8MT47aTwyPjtpPDM+O2k8ND47aTw1Pjs+O2w8dDxwPHA8bDxUZXh0Oz47bDwxMDs+Pjs+Ozs+O3Q8cDxwPGw8VGV4dDs+O2w8UHJvZmlsZSBJbmZvcm1hdGlvbiBTYXZlZDs+Pjs+Ozs+O3Q8cDxwPGw8VGV4dDs+O2w8U3VjY2Vzc0F1ZGl0Oz4+Oz47Oz47dDxwPHA8bDxUZXh0Oz47bDxyYXlwQHBjYWRtaW4uY3RjLmVkdTs+Pjs+Ozs+O3Q8cDxwPGw8VGV4dDs+O2w8OC8xNi8yMDA0IDE6Mjk6NTYgUE07Pj47Pjs7Pjt0PDtsP Gk8MT47PjtsPHQ8cDw7cDxsPG9uY2xpY2s7aHJlZjs+O2w8cmV0dXJuIGNvbmZpcm0oJ0FyZSB5b3Ugc3VyZSB5b3Ugd2FudCB0byByZW1vdmUgdGhpcyBub3RpZmljYXRpb24gaXRlbT8nKVw7O2phdmFzY3JpcHQ6X19kb1Bvc3RCYWNrKCdsbmtSZW1vdmVFdmVudCcsJzEwJyk7Pj4+Ozs+Oz4+Oz4+O3Q8O2w8aTwwPjtpPDE+O2k8Mj47aTwzPjtpPDQ+O2k8NT47PjtsPHQ8cDxwPGw8VGV4dDs+O2w8MTE7Pj47Pjs7Pjt0PHA8cDxsPFRleHQ7PjtsPFByb2ZpbGUgSW5mb3JtYXRpb24gU2F2ZWQ7Pj47Pjs7Pjt0PHA8cDxsPFRleHQ7PjtsPFN1Y2Nlc3NBdWRpdDs+Pjs+Ozs+O3Q8cDxwPGw8VGV4dDs+O2w8cmF5cEBwY2FkbWluLmN0Yy5lZHU7Pj47Pjs7Pjt0PHA8cDxsPFRl eHQ7PjtsPDgvMTYvMjAwNCAxOjM1OjU0IFBNOz4+Oz47Oz47dDw7bDxpPDE+Oz47bDx0PHA8O3A8bDxvbmNsaWNrO2hyZWY7PjtsPHJldHVybiBjb25maXJtKCdBcmUgeW91IHN1cmUgeW91IHdhbnQgdG8gcmVtb3ZlIHRoaXMgbm90aWZpY2F0aW9uIGl0ZW0/JylcOztqYXZhc2NyaXB0Ol9fZG9Qb3N0QmFjaygnbG5rUmVtb3ZlRXZlbnQnLCcxMScpOz4+Pjs7Pjs+Pjs+Pjt0PDtsPGk8MD47aTwxPjtpPDI+O2k8Mz47aTw0PjtpPDU+Oz47bDx0PHA8cDxsPFRleHQ7PjtsPDEyOz4+Oz47Oz47dDxwPHA8bDxUZXh0Oz47bDxQcm9maWxlIEluZm9ybWF0aW9uIFNhdmVkOz4+Oz47Oz47dDxwPHA8bDxUZXh0Oz47bDxTdWNjZXNzQXVkaXQ7Pj47Pjs7Pjt0PHA8cDxsPFRleHQ7Pjt sPHJheXBAcGNhZG1pbi5jdGMuZWR1Oz4+Oz47Oz47dDxwPHA8bDxUZXh0Oz47bDw4LzE2LzIwMDQgMTo1MjowMiBQTTs+Pjs+Ozs+O3Q8O2w8aTwxPjs+O2w8dDxwPDtwPGw8b25jbGljaztocmVmOz47bDxyZXR1cm4gY29uZmlybSgnQXJlIHlvdSBzdXJlIHlvdSB3YW50IHRvIHJlbW92ZSB0aGlzIG5vdGlmaWNhdGlvbiBpdGVtPycpXDs7amF2YXNjcmlwdDpfX2RvUG9zdEJhY2soJ2xua1JlbW92ZUV2ZW50JywnMTInKTs+Pj47Oz47Pj47Pj47dDw7bDxpPDA+O2k8MT47aTwyPjtpPDM+O2k8ND47aTw1Pjs+O2w8dDxwPHA8bDxUZXh0Oz47bDwxMzs+Pjs+Ozs+O3Q8cDxwPGw8VGV4dDs+O2w8UHJvZmlsZSBJbmZvcm1hdGlvbiBTYXZlZDs+Pjs+Ozs+O3Q8cDxwPGw8VGV4dD s+O2w8U3VjY2Vzc0F1ZGl0Oz4+Oz47Oz47dDxwPHA8bDxUZXh0Oz47bDxyYXlwQHBjYWRtaW4uY3RjLmVkdTs+Pjs+Ozs+O3Q8cDxwPGw8VGV4dDs+O2w8OC8xNi8yMDA0IDE6NTU6NDAgUE07Pj47Pjs7Pjt0PDtsPGk8MT47PjtsPHQ8cDw7cDxsPG9uY2xpY2s7aHJlZjs+O2w8cmV0dXJuIGNvbmZpcm0oJ0FyZSB5b3Ugc3VyZSB5b3Ugd2FudCB0byByZW1vdmUgdGhpcyBub3RpZmljYXRpb24gaXRlbT8nKVw7O2phdmFzY3JpcHQ6X19kb1Bvc3RCYWNrKCdsbmtSZW1vdmVFdmVudCcsJzEzJyk7Pj4+Ozs+Oz4+Oz4+O3Q8O2w8aTwwPjtpPDE+O2k8Mj47aTwzPjtpPDQ+O2k8NT47PjtsPHQ8cDxwPGw8VGV4dDs+O2w8MTQ7Pj47Pjs7Pjt0PHA8cDxsPFRleHQ7PjtsPFByb2Zpb GUgSW5mb3JtYXRpb24gU2F2ZWQ7Pj47Pjs7Pjt0PHA8cDxsPFRleHQ7PjtsPFN1Y2Nlc3NBdWRpdDs+Pjs+Ozs+O3Q8cDxwPGw8VGV4dDs+O2w8cmF5cEBwY2FkbWluLmN0Yy5lZHU7Pj47Pjs7Pjt0PHA8cDxsPFRleHQ7PjtsPDgvMTYvMjAwNCAxOjU4OjMwIFBNOz4+Oz47Oz47dDw7bDxpPDE+Oz47bDx0PHA8O3A8bDxvbmNsaWNrO2hyZWY7PjtsPHJldHVybiBjb25maXJtKCdBcmUgeW91IHN1cmUgeW91IHdhbnQgdG8gcmVtb3ZlIHRoaXMgbm90aWZpY2F0aW9uIGl0ZW0/JylcOztqYXZhc2NyaXB0Ol9fZG9Qb3N0QmFjaygnbG5rUmVtb3ZlRXZlbnQnLCcxNCcpOz4+Pjs7Pjs+Pjs+Pjs+Pjs+Pjt0PHA8cDxsPFRleHQ7PjtsPFBhZ2UgMSBvZiAxNDE7Pj47Pjs7Pjs+Pjs+ Pjs+Pjs+Pjs+Pjs+66yMSsisMGwArlHk3eyFer6hwP8=" /> 
Viewstate Size: 6681 Bytes (6.6K)  <-- Datagrids can cause much bigger values than this, even up to 10K+ 

Notice that the encoded value does not contain binary characters, non printable characters, or even “s that would interfere with the HTML. Very convenient.

Reducing Viewstate:

For many, the simple solution is to turn off the view state property in the datagrid. This results in a reduction to:

<input type="hidden" name="__VIEWSTATE" 
value="dDwtMTkyNjUyMzE4Mjt0PDtsPGk8MD47PjtsPHQ8O2w8aTw0Pjs+O2w8dDw7bDxpPDEyPjtpPDEzPjs+O2w8dDw7bDxpPDA+Oz47bDx0PDtsPGk8MTc+O2k8MTk+Oz47bDx0PHA8cDxsPFRleHQ7PjtsPEdvb2QgTW9ybmluZzs+Pjs+Ozs+O3Q8cDxwPGw8VGV4dDs+O2w8cmF5cEBwY2FkbWluLmN0Yy5lZHU7Pj47Pjs7Pjs+Pjs+Pjt0PDtsPGk8Mz47PjtsPHQ8O2w8aTwzPjs+O2w8dDxwPHA8bDxUZXh0Oz47bDxQYWdlIDEgb2YgMTQxOz4+Oz47Oz47Pj47Pj47Pj47Pj47Pj47PlVonF2dspWHNoR0dJ1oK6nDCogm" /> 
Viewstate Size: 389 Bytes (.4k) <-- This is the viewstate required by 
other non datagrid related controls on my page.

While that looks great, you will soon find that many features are now
disabled. You can no longer sort properly, none of the datagrid events fire properly, you have to refresh your data every time the page refreshes, paging quits working, etc. Some have found ways to get around all this, but the time it takes often outweighs the benefits. Some opt at this point to go find another control and scrap the datagrid all together. I have found that the power of the datagrid is worth a little effort and that if you have a ready made template to draw from, then you can take advantage of the advanced features while still reducing your viewstate considerably.

A compromise:

We generally aren’t worried about a few hundred bytes, and it sure is a
whole lot of work to code around a datagrid that just lays there like a limp fish. The compromise here is to leave the viewstate on the datagrid on, but turn off the viewstate on all of the the components that end up on the page – namely the data row items. The datagrid has a handy event called ItemCreated which is fired once for every row that is rendered to the screen. When this event is fired, we can simply turn the viewstate off for this item. Keep in mind that this turns off the viewstate for the whole row. If the viewstate of a parent is off, all child controls also loose their viewstate. This means that any child cells, link buttons, etc loose their viewstate too. The code below shows the finished event as it would look in code.

Private Sub dgMyDgrid_ItemCreated(ByVal sender As Object, ByVal e As 
System.Web.UI.WebControls.DataGridItemEventArgs) Handles 
dgNotificationList.ItemCreated
        e.Item.EnableViewState = False
End Sub

Pretty simple eh? Lets look at the viewstate when the datagrid is enabled but its children aren’t.

<input type="hidden" name="__VIEWSTATE" value="
dDwtMTkyNjUyMzE4Mjt0PDtsPGk8MD47PjtsPHQ8O2w8aTw0Pjs+O2w8dDw7bDxpPDEyPjtpPDEzPjs+O2w8dDw7bDxpPDA+Oz47bDx0PDtsPGk8MTc+O2k8MTk+Oz47bDx0PHA8cDxsPFRleHQ7PjtsPEdvb2QgTW9ybmluZzs+Pjs+Ozs+O3Q8cDxwPGw8VGV4dDs+O2w8cmF5cEBwY2FkbWluLmN0Yy5lZHU7Pj47Pjs7Pjs+Pjs+Pjt0PDtsPGk8Mz47PjtsPHQ8O2w8aTwxPjtpPDM+Oz47bDx0PEAwPHA8cDxsPFZpcnR1YWxJdGVtQ291bnQ7UGFnZUNvdW50O18hSXRlbUNvdW50O18hRGF0YVNvdXJjZUl0ZW1Db3VudDtEYXRhS2V5czs+O2w8aTwxNDAyPjtpPDE0MT47aTwxMD47aTwxNDAyPjtsPD47Pj47PjtAMDxAMDxwPGw8SGVhZGVyVGV4dDs+O2w8aWQ7Pj47Ozs7PjtAMDx wPGw8SGVhZGVyVGV4dDs+O2w8RXZlbnQ7Pj47Ozs7PjtAMDxwPGw8SGVhZGVyVGV4dDs+O2w8VHlwZTs+Pjs7Ozs+O0AwPHA8bDxIZWFkZXJUZXh0Oz47bDxDYXVzZWQgQnkgVXNlcjs+Pjs7Ozs+O0AwPHA8bDxIZWFkZXJUZXh0Oz47bDxMb2dnZWQgQXQgXDxJTUcgSEVJR0hUPThweCBXSURUSD04cHggQk9SREVSPTAgc3JjPScvYXJ0L2Rvd24ucG5nJyAvXD47Pj47Ozs7PjtAMDxwPGw8SGVhZGVyVGV4dDs+O2w8QWN0aW9uczs+Pjs7Ozs+Oz47Ozs7Ozs7Ozs+Ozs+O3Q8cDxwPGw8VGV4dDs+O2w8UGFnZSAxIG9mIDE0MTs+Pjs+Ozs+Oz4+Oz4+Oz4+Oz4+Oz4+Oz66V9WQsY6x9IVtOTOsjeJl7Y3I0Q==" /> 
Viewstate Size: 969 Bytes (1K)

969 – 389 = 580 Bytes. The 389 in this case is the viewstate from other
items on the page I am using as a reference. This means that the datagrid is now using about 580 Bytes instead of (6681 – 389 = 6292 Bytes). That’s quite a significant difference. The best part is that the events for
sorting and paging will still fire properly!

Were not done yet:

While the sorting and paging events still fire properly, you may find that events for data rows do not (e.g.: Remove link button to drop the selected record). If they do still work, that means that you probably populate your datagrid in the Page_Load event. An interesting thing about firing events for controls is that they have to be instantiated before or in the Page_Load event for their event to fire properly. Any events for controls that don’t exist yet when the event is ready to fire are simply dropped. Since any link buttons (or other controls) added to a data row are dynamic, the datagrid has to have already re-populated itself with these controls for them to fire events properly. Lets look at the example of clicking the remove button to delete a record. If a user views the datagrid, they see a list of data. When they click Remove, the Page_Load event fires, your code repopulates the datagrid with the current information, the Item Command event can now fire with the command name and command argument of the source control. Now since the data has changed, you may need to refresh your data source with the new information, then the result is rendered to the user. You may or may not have noticed that you refresh your datagrid twice.
Weather you use caching or other techniques to help speed this process,
binding data to your control multiple times.

Avoiding Multiple Refresh:

Be aware, that the datagrid itself isn’t dynamic, just its child items such as data rows. This being the case, events for the datagrid itself (sorting, paging, etc) should work just fine as long as it’s viewstate is enabled. I myself prefer to call my data refresh from the Page_PreRender event. By now, everything should be figured out, all events should have been fired, and all you need to do is grab the current data set (I also prefer to use data chunks in many cases, but that is another article in it self). This sounds good except that for a button in a data row to fire properly, it has to be created long before the PreRender event or the event will be dropped. An easy way to get around this is to hijack the event of another button. What is the difference between a link button in a data row and any other link button on the page? The main difference is that generally the ID or other primary key of the selected data indicating which item to remove, change, etc. Other than that, you just want an event to fire in response to the click.

Hijacking Events:

A data list with one hundred entries, each with its own remove link have one thing in common. However you implement the process, all those link buttons fire the same event with an id or some other primary key indicating which item to remove. This being the case, does it matter if the datagrid itself receives the event, or can another control all together receive the event? To keep the viewstate low, I opted to use another control completely. I
added a new link button to the page (outside the datagrid) and set its text property to “” (empty) and its CommandName property to “Remove”. You want this control to render to the page so don’t change the visible attribute, but you eliminate any visible sign it is there by clearing the text
property. Next, name the control so that it makes sense (in my case,
lnkRemove). We will make the command event fire when one of the Remove
links is clicked for a data item. Note that this new link control is not dynamic and therefore is instantiated already when it is time to fire
events. Create the Command event for the link button as shown below.

Private Sub lnkRemove_Command(ByVal sender As Object, ByVal e As 
System.Web.UI.WebControls.CommandEventArgs) Handles lnkRemoveEvent.Command   ' NOTE: the last_event_arg variable is a global variable and will be 
covered elsewhere.
        Dim id As Int64
        Try
            id = Convert.ToInt64(last_event_arg)  ' Try to convert the 
argument to a numeric value
        Catch ex As Exception
            id = 0
        End Try
        RemoveItemItem(id)  ' This function contains the logic to actually remove the item from the database, etc..
End Sub

Now that we have an event waiting to fire, we can set all of our Remove
links in the datagrid to use it. Because these datagrid link buttons are all created dynamically, we have to do the hooking in code. For each row to be displayed, the ItemDataBound event gets fired. During this process we can add a nice javascript confirm message (are you sure you want to remove) and at the same time hijack the event of our stray link button thereby sending all events from any of the datagrid remove links to the stray link buttons event handler.

Private Sub dgMyDataGrid_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.DataGridItemEventArgs) Handles 
dgNotificationList.ItemDataBound
 'NOTE: We only want to change items or alt items.  If we try this on 
header, footer, etc. rows, it won't work (they shouldn't have remove 
buttons).
        If (e.Item.ItemType = ListItemType.AlternatingItem Or 
e.Item.ItemType = ListItemType.Item) Then
            Dim lnk As LinkButton
            Dim ds As Data.Common.DbDataRecord  ' NOTE: I believe this 
datatype changes depending on what is set to the datasource property
      ' of the datagrid.  I am using a DataReader, where I believe a 
datarowview object should be used when bound to a dataset
            ds = CType(e.Item.DataItem, Data.Common.DbDataRecord)
            lnk = 
CType(e.Item.Cells(2).FindControl("lnkRemoveNotification"), LinkButton)  ' Find the current link button
            If (Not lnk Is Nothing) Then
     ' Add the javascript confirm box so they have to click yes to remove
                lnk.Attributes.Add("onclick", "return confirm('Are you sure you want to remove this notification item?');") 
     ' This is where we hijack the post back event handler of the stray link button.  This allows this link button to      ' send its events to a different control.
     ' NOTE: the current ID is extracted from the current data row (ds) and added as the event argument to be sent with the post back                 lnk.Attributes.Add("href", "javascript:" + 
Page.GetPostBackEventReference(lnkRemoveEvent, ds("id").ToString()))
            End If
        End If
End Sub

Passing Command Arguments

In the previous code snippet showed the GetPostBackEventReference function. This function sets the current data row’s link button to send its events to a different control. The second parameter (the current items id) is sent as its argument. When using this technique, I have noticed that the argument isn’t passed properly all the way through the stack. By the time the
Command event fires for the stray link button, the command argument will be set to it’s default value every time, thereby loosing the ID of the data item in question. It is actually being sent, but is getting crossed up somewhere along the way. A quick fix for this is to grab the event argument that is passed from the form during the Page_Load phase. Once this is set, the event can get the current id from the global variable.

Dim last_event_arg As String

Private Sub Page_Load(ByVal sender As System.Object, ByVal e As 
System.EventArgs) Handles MyBase.Load
        ' Extract the event arg from the form and put it in the global 
variable.
        last_event_arg = Request("__EVENTARGUMENT")
End Sub

Pretty simple eh? Now you have the best of both worlds, a small view state and working, paging, sorting datagrid. The nice thing here is that you get to take advantage of the ease of the datagrid with its viewstate on, and keep your viewstate size down. Using this template, you can build the same features for about the same amount of work and get a much more efficient component.

Ray Pulsipher

Owner

Computer Magic And Software Design

Comments are closed.


Home | My Blog | Products | Edumed | About Us | Portfolio | Services | Location | Contact Us | Embedded Python | College Courses | Quick Scan | Web Spy | EZ Auction | Web Hosting
This page has been viewed 827231 times.

Copyright © 2005 Computer Magic And Software Design
(360) 417-6844
computermagic@hotmail.com
computer magic