0
\$\begingroup\$

Following the normal pattern of adding inline scripts to gridview row/s is a bad practice it used to work like below

 protected void CustomersGrid_RowDataBound(object sender, GridViewRowEventArgs e)
    {
        switch (e.Row.RowType)
        {
            case DataControlRowType.DataRow:
                DataRowView drv = (DataRowView)e.Row.DataItem;
                if (drv != null)
                {
                    string sKey = drv["Id"].ToString();                                e.Row.Attributes.Add("onclick","location.href='manage.aspx?="+sKey+"'");
                }
                break;         
        }
    }

hence i switched over to event registration pattern which worked like below

protected void CustomersGrid_RowDataBound(object sender, GridViewRowEventArgs e)
    {
        switch (e.Row.RowType)
        {
            case DataControlRowType.Header:
                StringBuilder _sbDynamicScript = new StringBuilder();
                _sbDynamicScript.AppendLine("Sys.Application.add_load(function(){");
                _sbDynamicScript.AppendLine("try{");
                break;
            case DataControlRowType.DataRow:
                DataRowView drv = (DataRowView)e.Row.DataItem;
                if (drv != null)
                {
                    string sKey = drv["Id"].ToString();
                    e.Row.Attributes.Add("id", randomNumber);
                    _sbDynamicScript.AppendLine("if($get('" + randomNumber + "'))$addHandler($get('" + randomNumber + "'),'click',function(evnt){location.href='manage.aspx?id='="+ sKey +"'})");
                }
                break;
            case DataControlRowType.Footer:
                _sbDynamicScript.AppendLine("}catch(err){alert(err.message)}})");
                if (!Page.ClientScript.IsStartupScriptRegistered(GetType(), "customerapp"))
                {
                    Page.ClientScript.RegisterStartupScript(GetType(), "customerapp", _sbDynamicScript.ToString(), true);
                }
                Session["clientScript"] = _sbDynamicScript.ToString();
                break;
        }
    }

notice rowType is used to create dynamic script. Here's something that's happening up there

1.add a random number as ID for the gridview row

2.then add a click event handler using the asp.net ajax

  1. make the make navigate away on click

Bug's ahoy:

Notice that in footer template i have put that script into session, that was my mistake. You see the scripts registered using registerstartup script are not persisted on postbacks and have to be re-registered. i have put a check on PageLoad to do below

 if (!Page.ClientScript.IsStartupScriptRegistered(GetType(), ""))
            {
                Page.ClientScript.RegisterStartupScript(GetType(), "customerapp", Session["clientScript"].ToString(), true);
            }

notice the script is registered from session!! Well it happens some times that the Gridview records are changed by postback. But since session has already the key in it, the rowdatabound event script fails to get registered with new script. So what do i do in this situation. Can i get some other way to persist the script and make it run whenever gridview binds again

btw the script registered will look like below

Sys.Application.add_load(function () {
    try {
        if ($get('ElSxrM4myH4%3d')) {
            $addHandler($get('ElSxrM4myH4%3d'), 'click', function (evnt) {})
        }
    } catch (err) {
        alert(err.message)
    }
})
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

Would it not be better to build a generic script to handle all row scripting requirements, and include once per page? You'll end up with a cleaner end script, and your page footprint will be a lot smaller. You'll also benefit from the browser's resource caching.

Using jQuery, you could achieve something like:

$(function() {
    $("tr.needEvent td").live(function() {
        // Event handler code goes here.
    });
});

where tr.needEvent is a class appended to the <tr> used to wrap a row. If you aren't using tables, this could be used the same way with <div> or any other container element. The important thing is, using .live() we can run the code once, and any other elemnets added to the page that match that selector, will be bound to the event handler automatically.

The use of $(function() { is the jQuery equivalent of Sys.Application.add_load(function() {

\$\endgroup\$
5
  • \$\begingroup\$ you recommend separating scripting behavior from page markup? Great Idea just that how will i add event handlers to table row's of the grid when i can't predict them [as it is generated at runtime]. Does anything else run through your mind, mine is blank right now \$\endgroup\$ Jun 3, 2011 at 4:01
  • \$\begingroup\$ jQuery has great support for persistent events using .live. I've updated my answer. \$\endgroup\$ Jun 3, 2011 at 6:05
  • \$\begingroup\$ I'm still not satisfied with the answer. I will vote up but definitely not a answer \$\endgroup\$ Jun 3, 2011 at 6:55
  • \$\begingroup\$ @Deeptechtons - What are you looking for in an answer? \$\endgroup\$ Jun 3, 2011 at 7:45
  • \$\begingroup\$ thanks for inquiring again, questions says most of it. In certains cases, another button somewhere on the webform might cause postback which doesn't rebind the Gridview in that cause the script won't be registered is it wasn't for session. I feel using session is costly too, and it creates another problem when gridview rebinds.On the Page_Load the script was already registered from session and the new script generated inside row_databound would fail get my point now? \$\endgroup\$ Jun 3, 2011 at 8:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.