7

I have a gridview inside an updatepanel. One of the fields in the gridview is an ASP.net linkbutton like so:

 <ItemTemplate>
       <asp:LinkButton ID="hlSortOrder" runat="server" CssClass="hlDialog" OnClick="LoadLog"
        Text='<%# DataBinder.Eval(Container, "DataItem.SortOrder") %>'></asp:LinkButton>
  </ItemTemplate>

When someone clicks the linkbutton I call the OnClick method that I created called LoadLog. LoadLog looks like this:

protected void LoadLog(object sender, EventArgs e)
        {
            GridViewRow gr = (GridViewRow)((DataControlFieldCell)((LinkButton)sender).Parent).Parent;
            Label l = (Label)gr.FindControl("lblID");
            DataSet ds;

            ds = BL.GetRunoffAnswerLog(Convert.ToInt64(l.Text));

            if (ds != null)
            {
                if (ds.Tables[0].Rows.Count == 0)
                {
                    gvLog.Visible = false;
                    gvLog.DataSource = null;
                    lblRowsCount.Text = "No log for this record!";
                }
                else
                {
                    lblRowsCount.Text = ds.Tables[0].Rows.Count.ToString() + " row(s) found for this record.";
                    gvLog.DataSource = ds.Tables[0];
                    gvLog.DataBind();
                    gvLog.Visible = true;
                }
            }
            ScriptManager.RegisterClientScriptBlock(this, this.GetType(), "openDialog", "$('#dialog').dialog({draggable: true, modal: true, height: 500, width: 750, title: 'Log', open: function (type, data) {$(this).parent().appendTo('form');}});", true);
        }

Basically it gets a handle of the grid view row, pulls some data back from the database and assigns it to the gvLog source. After that notice the line at the end:

ScriptManager.RegisterClientScriptBlock(this, this.GetType(), "openDialog", "$('#dialog').dialog({draggable: true, modal: true, height: 500, width: 750, title: 'Log', open: function (type, data) {$(this).parent().appendTo('form');}});", true);

I have to do this so that I can open up my dialog box. When I click a row in my gridview ONLY the first time I get this:

enter image description here

Notice it only really shows the title...weird. But once I click that same row again it shows the entire dialog:

enter image description here

It only happens on the first click, if I keep clicking different rows it works fine. I should add that I had to add the following jquery code:

 <script type="text/javascript">
        $(document).ready(function () {
            var prm = Sys.WebForms.PageRequestManager.getInstance();

            prm.add_endRequest(function () {
                $("#dialog").hide();
                // re-bind your jQuery events here 
           });
        ....more code...

Based on this discussion: jQuery $(document).ready and UpdatePanels?

If I do not have that code the minute a post back happens the entire div that this dialog is inside always gets shown on my page and I dont want that...

As one of the members below has mentioned. I believe what is happening is the first time you click the linkbutton the client side event is happening first which is opening the actual open dialog, even though I raise this event in server side code...as you see above only when you click the "LoadLog" event click do I register this jquery opendialog. But it appears that this still opens the dialog the first time and once you click it the second time only then is the data shown.

Community
  • 1
  • 1
oJM86o
  • 2,108
  • 8
  • 43
  • 71
  • Can you show the full structure of your layout? Where is the 'form' element? Also, it would be really useful to see a live example of this. That would definitely help a lot. Anyway you could provide an example? – Michael Frederick Jun 29 '12 at 22:10
  • Have you tried doing this without an `UpdatePanel` i.e. by making a full postback? – Anchit Jul 05 '12 at 19:21
  • @Anchit - without an updatepanel will not display the dialog at all...remember this is jquery and asp.net. – oJM86o Jul 06 '12 at 15:06
  • place a `` on your page and try to set this Label's `Text` property to your jQuery code. – Anchit Jul 07 '12 at 18:19
  • Anchit what you are describing is not feasible for me sorry. – oJM86o Jul 09 '12 at 15:42
  • @oJM86o - I would love to hear if you have had a chance to try my answer or have any comments. – Peter Jul 09 '12 at 17:20
  • Peter I wanted to try your solution but I am having a hard time understanding it. It mentioned to not create my dialog in code behind, but my implementation is just registering the open dialog not really openining it from code behind. My javascript is a bit rusty so it is difficult to use your solution. If we could do a chat maybe it will help? – oJM86o Jul 09 '12 at 17:25
  • @oJM86o - I updated my answer to include a working example. The example has some dummy data. When you click the link button it does an async post, loads some dummy "log" data, binds it to the log gridview, and calls the "showLog" javascript function. This function moves the log grid view into the dialog and shows it. – Peter Jul 10 '12 at 20:40

4 Answers4

3

I have had a lot of issues with jQuery awesomeness and UpdatePanels. Try this approach:

  1. Place the div that you are using for your dialog outside of your update panel. Don't create your dialog in code behind. Instead create your dialog on page load. Since your dialog is outside the updatepanel it won't get clobbered. Make sure to not auto-open it.
  2. Add an additional div to your dialog div to hold your content.
  3. Create a javascript function that
    • clears the contents of the content div in your dialog of any previous content
    • appends the gvLog control to the dialog content div, something like $('#dialogContent').append($('#<%= gvLog.ClientID %>'));
    • shows the dialog
  4. Now in your code behind tweak the RegisterClientScriptBlock to call this new javascript function.

Example Code
Code Behind:

public partial class _Default : System.Web.UI.Page 
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!Page.IsPostBack)
        {
            //load in some dummy data
            Dictionary<int, string> vals = new Dictionary<int, string>()
            {
                {1, "ONE"},
                {2, "TWO"},
                {3, "THREE"},
                {4, "FOUR"},
                {5, "FIVE"},
                {6, "SIX"}
            };

            gvData.DataSource = vals;
            gvData.DataBind();
        }
    }

    protected void LoadLog(object sender, EventArgs e)
    {
        LinkButton lb = (LinkButton)sender;
        var key = lb.CommandArgument;

        Random r = new Random();
        Dictionary<int, int> dict = new Dictionary<int, int>();

        for (int i = 0; i <= r.Next(5, 20); i++)
        {
            dict.Add(r.Next(), r.Next());
        }

        gvLog.DataSource = dict;
        gvLog.DataBind();

        //show log in dialog on client
        ScriptManager.RegisterStartupScript(up, up.GetType(), "openDialog", "showLog();", true);
    }
}

Designer Code:

<%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <script src="Scripts/jquery-1.7.2.min.js" type="text/javascript"></script>
    <script src="Scripts/jquery-ui-1.8.21.custom.min.js" type="text/javascript"></script>
    <link href="ui-lightness/jquery-ui-1.8.21.custom.css" rel="stylesheet" type="text/css" />

    <script type="text/javascript">
        $(function () { 
            //setup dialog
            $('#dialog').dialog({draggable: true, 
                                modal: true, 
                                height: 500, 
                                width: 750, 
                                title: 'Log',
                                autoOpen: false});
        });

        function showLog() {
            //clear any old log data
            $('#dvContent').empty();
            //append current log
            $('#<%= gvLog.ClientID %>').appendTo($('#dvContent'));
            //show dialog
            $('#dialog').dialog('open');
        }
    </script>
</head>

<body>
    <form id="form1" runat="server">
    <asp:ScriptManager ID="sp" runat="server" />
    <div>
        <asp:UpdatePanel ID="up" runat="server">
            <ContentTemplate>
                <asp:GridView ID="gvData" runat="server">
                    <Columns>
                        <asp:TemplateField>
                            <ItemTemplate>
                                <asp:LinkButton ID="lbShowLog" runat="server" Text="Show Log" 
                                    OnClick="LoadLog" CommandArgument='<%# Eval("Key") %>' />
                            </ItemTemplate>
                        </asp:TemplateField>
                    </Columns>
                </asp:GridView>

                <div style="display:none;">
                    <asp:GridView ID="gvLog" runat="server">
                    </asp:GridView>
                </div>
            </ContentTemplate>
        </asp:UpdatePanel>
    </div>

    <div id="dialog" style="display:none;">
        <div id="dvContent">

        </div>
    </div>
    </form>
</body>
</html>
Peter
  • 9,643
  • 6
  • 61
  • 108
  • +1 for this answer. I also had a lot of trouble with UpdatePanels - until I removed them from the page and used pure HTML controls in combination with jQuery, jQueryUI and AJAX calls. Because UpdatePanels generate a lot of JavaScript code themselves, there are side effects with it. – Matt Jul 09 '12 at 16:15
  • @oJM86o - Let me know if this updated answer will work for you. Hopefully the sample code will point you in the right direction. – Peter Jul 13 '12 at 16:34
0

See this

Try adding a call to $('#dialog').dialog('open')

your first call to $('#dialog').dialog([Parmas]) may be creating it but not opening it.

Something like this:

 ScriptManager.RegisterClientScriptBlock(this, this.GetType(), "openDialog", "$('#dialog').dialog({draggable: true, modal: true, height: 500, width: 750, title: 'Log', open: function (type, data) {$(this).parent().appendTo('form');}});$('#dialog').dialog('open');", true);

HTH

Simon Dugré
  • 17,980
  • 11
  • 57
  • 73
brian chandley
  • 1,276
  • 1
  • 10
  • 20
  • Unfortunately this is the same issue I am running into...when it first opens it doesnt show any data... – oJM86o Jul 05 '12 at 16:46
0

Try modifying your DOM before opening the dialog

In code :

ScriptManager.RegisterClientScriptBlock(this, this.GetType(), "openDialog", "$(this).parent().appendTo('form');

In JS :

$('#dialog').dialog({draggable: true, modal: true, height: 500, width: 750, title: 'Log', true);
Simon Dugré
  • 17,980
  • 11
  • 57
  • 73
Nexus
  • 294
  • 2
  • 5
  • What you have posted is what I already have, what is the exact difference between yours and mine??? – oJM86o Jul 06 '12 at 14:56
  • 1
    But did you try what i suggested, my error to leave the original code in there. But giving -1 just because you didn't got the message, feels harsh. Anyway adapted what i forgot earlier – Nexus Jul 06 '12 at 15:23
  • I think your clientside opendialog click happens before your serverside code, so basicly you will see only the details on the second click – Nexus Jul 09 '12 at 08:43
  • and how do I go about fixing this that is the reason for this question. – oJM86o Jul 09 '12 at 15:36
  • Not sure if this fixes it but try wrapping your code in a document.ready like so: ScriptManager.RegisterClientScriptBlock(this, this.GetType(), "openDialog", "$(function(){$('#dialog').dialog({draggable: true, modal: true, height: 500, width: 750, title: 'Log', open: function (type, data) {$(this).parent().appendTo('form');}});});", true); – Nexus Jul 10 '12 at 13:12
  • what exactly do you want me to put this? I already have this in my code behind, that is what I am trying to tell you, everything you are posting is already what I have... – oJM86o Jul 10 '12 at 16:32
0

There is a very tricky solution for your problem that will save you from all the hassle of the update panel and the jquery.

First, we will not depend on the RegisterClientScriptBlock function and instead everything will be done through hidden fields.

  1. Create a hidden field that will flag if the show dialog to be show or not.
  2. Create a javascript function that check if hidden field has value or not. If the hidden field had value, display the show dialog and depend on hidden fields to get the data else don't show the dialog, this will fix the problem of the post back show dialog issue.
  3. add an animation extender to the update panel

<cc1:UpdatePanelAnimationExtender ID="UpdatePanelAnimationExtender1" TargetControlID="UpdatePanel1" runat="server"> <Animations> <OnUpdated> <Parallel duration="0">
<ScriptAction Script="YouFunctionCall();" /> </Parallel> </OnUpdated> </Animations> </cc1:UpdatePanelAnimationExtender>

and at the end of this javascript function clear the hidden field.

So what will happen, at post back the javascript will run to check if the flag is set or not and it will find that the flag is empty and when you click inside the update panel, your server side code will run and set the hidden field flag and any other information needed then the update panel animation extender will run the javascript function after the update panel have been updated and will check the hidden field and find it filled with data and will trigger the show dialog and then reset the flag so any other post back will not show the dialog.

Samir Adel
  • 2,691
  • 2
  • 15
  • 16