This is a migrated thread and some comments may be shown as answers.

Button inside RadWindow Content Template Will Not PostBack Asynchronously (Nor will it call server-side validation)

7 Answers 404 Views
Window
This is a migrated thread and some comments may be shown as answers.
Merritt
Top achievements
Rank 1
Merritt asked on 08 Mar 2012, 08:58 PM
Weird issue with editing: see reply.

7 Answers, 1 is accepted

Sort by
0
Merritt
Top achievements
Rank 1
answered on 08 Mar 2012, 11:45 PM
This doesn't work, but should given the assumptions I have made about the RadWindow and RadAjaxManager:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Test.aspx.cs" Inherits="WIIIP.Admin.Users.Test" %>
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
 
    <asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
     
    <telerik:RadAjaxManager ID="RadAjaxManager1" runat="server">
        <AjaxSettings>
            <telerik:AjaxSetting AjaxControlID="Panel1">
                <UpdatedControls>
                    <telerik:AjaxUpdatedControl ControlID="Panel1" />
                    <telerik:AjaxUpdatedControl ControlID="Panel2" />
                </UpdatedControls>
            </telerik:AjaxSetting>
            <telerik:AjaxSetting AjaxControlID="Button2">
                <UpdatedControls>
                    <telerik:AjaxUpdatedControl ControlID="Panel2" />
                    <telerik:AjaxUpdatedControl ControlID="Panel1" />
                </UpdatedControls>
            </telerik:AjaxSetting>           
        </AjaxSettings>
    </telerik:RadAjaxManager>
 
    <asp:Panel ID="Panel1" runat="server" style="border: 1px solid red">
        <h1>Panel 1</h1>
        Was last Postback was Asynchronous? <b><asp:Literal ID="Literal1" runat="server"></asp:Literal></b>
        <br /><br />
        <asp:Button ID="Button1" Text="Open RadWindow1" runat="server" OnClick="Button1_Click" />
    </asp:Panel>
    <asp:Panel ID="Panel2" runat="server">
        <telerik:RadWindow ID="RadWindow1" runat="server" Behaviors="Close" EnableShadow="true" Modal="true" VisibleOnPageLoad="false" >
            <ContentTemplate>
                    <asp:Button runat="server" ID="Button2" OnClick="Button2_Click" Text="Close RadWindow1." />
            </ContentTemplate>
        </telerik:RadWindow>
    </asp:Panel>
 
    </form>
</body>
</html>

Here is the code behind:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
 
namespace WIIIP.Admin.Users
{
    public partial class Test : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            Literal1.Text = ScriptManager1.IsInAsyncPostBack.ToString();
            //ScriptManager1.RegisterAsyncPostBackControl(Button2);
        }
 
        protected void Button1_Click(object sender, EventArgs e)
        {
            RadWindow1.VisibleOnPageLoad = true;
        }
 
        protected void Button2_Click(object sender, EventArgs e)
        {
             
            RadWindow1.VisibleOnPageLoad = false;
        }
    }
}

When the button inside the RadWindow is clicked, it does a full postback. You can fiddle around and change the RadAjaxManager settings, for instance, by replacing Button2 with Panel2, but you'll still get the same results.

In my next post, I will show the code I have used to get it to work, but do not like because of the use of update panels.

0
Merritt
Top achievements
Rank 1
answered on 08 Mar 2012, 11:50 PM
So this code works, but I don't like having to wrap everything in an UpdatePanel. Time and time again, I have to hack solutions together with your control set because the controls in the set don't properly behave when interacting with each other. Please tell me there is something I am missing here:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Test.aspx.cs" Inherits="WIIIP.Admin.Users.Test" %>
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
 
    <asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
 
    <asp:UpdatePanel runat='server'>
        <ContentTemplate>
            <asp:Panel ID="Panel1" runat="server" style="border: 1px solid red">
                <h1>Panel 1</h1>
                Was last Postback was Asynchronous? <b><asp:Literal ID="Literal1" runat="server"></asp:Literal></b>
                <br /><br />
                <asp:Button ID="Button1" Text="Open RadWindow1" runat="server" OnClick="Button1_Click" />
            </asp:Panel>
            <asp:Panel ID="Panel2" runat="server">
                <telerik:RadWindow ID="RadWindow1" runat="server" Behaviors="Close" EnableShadow="true" Modal="true" VisibleOnPageLoad="false" >
                    <ContentTemplate>
                            <asp:Button runat="server" ID="Button2" OnClick="Button2_Click" Text="Close RadWindow1." />
                    </ContentTemplate>
                </telerik:RadWindow>
            </asp:Panel>
        </ContentTemplate>   
    </asp:UpdatePanel>
 
    </form>
</body>
</html>

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
 
namespace WIIIP.Admin.Users
{
    public partial class Test : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            Literal1.Text = ScriptManager1.IsInAsyncPostBack.ToString();
            ScriptManager1.RegisterAsyncPostBackControl(Button2);
        }
 
        protected void Button1_Click(object sender, EventArgs e)
        {
            RadWindow1.VisibleOnPageLoad = true;
        }
 
        protected void Button2_Click(object sender, EventArgs e)
        {
             
            RadWindow1.VisibleOnPageLoad = false;
        }
    }
}


0
Merritt
Top achievements
Rank 1
answered on 09 Mar 2012, 12:42 AM
So to update: this control cannot be considered in the same way one would consider most controls you plant on the page because of the way it is inserted in the DOM (or whatever). apparently it's appended in a way that prevents if from being properly associated with other controls or ajax/async update policies in play:

 the RadWindow's content is moved in the DOM tree when it is created - i.e. the child controls are not in the same place in the generated HTML where they are in the ASPX markup 

http://www.telerik.com/help/aspnet-ajax/radwindow-ajaxifying.html 

Despite the fact that this somewhat contridicts with the results I experienced by putting it all in one update panel, I am going to ignore those results and start focusing on considering the window's content disparate from the rest of the page and only accessible via javascript interactions:

My current strategy is based on this demo:

http://demos.telerik.com/aspnet-ajax/controls/examples/integration/gridandwindow/defaultcs.aspx?product=window 

I'll be posting my test code when things are working.
0
Merritt
Top achievements
Rank 1
answered on 09 Mar 2012, 02:07 AM
Well, I think my current code works. I introduced a user control because my situation warrents it, but it can be done without one i believe:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Test.aspx.cs" Inherits="WIIIP.Admin.Users.Test" %>
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
     
    <script type="text/javascript">
        function openWinContentTemplate() {
            $get("IsTestControlLoaded").value = true;
            $find("<%= RadWindow1.ClientID %>").show();
            return false;
        }
 
        function closeWindow() {
            $find("<%= RadWindow1.ClientID %>").close();
        }
         
        function OnClientClose(sender, eventArgs) {
            $get("IsTestControlLoaded").value = false;
        }
         
    </script>
 
    <asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
     
    <telerik:RadAjaxManager ID="RadAjaxManager1" runat="server">
        <AjaxSettings>
            <telerik:AjaxSetting AjaxControlID="Button1">
                <UpdatedControls>
                    <telerik:AjaxUpdatedControl ControlID="PlaceHolder1" />
                </UpdatedControls>
            </telerik:AjaxSetting>
            <telerik:AjaxSetting AjaxControlID="PlaceHolder1">
                <UpdatedControls>
                    <telerik:AjaxUpdatedControl ControlID="Literal1" />
                </UpdatedControls>
            </telerik:AjaxSetting>
        </AjaxSettings>
    </telerik:RadAjaxManager>
     
    <asp:HiddenField ID="IsTestControlLoaded" runat="server" Value="false" />
     
    <asp:Panel ID="Panel1" runat="server">
        <h1>Panel 1</h1>
        Value entered from radwindow: <b><asp:Literal ID="Literal1" runat="server" ></asp:Literal></b>
         
        <br /><br />
        <asp:Button ID="Button1" Text="Open RadWindow1" runat="server" OnClick="Button1_Click" />
    </asp:Panel>
     
    <telerik:RadWindow ID="RadWindow1" runat="server" Behaviors="Close" EnableShadow="true" Modal="true" OnClientClose="OnClientClose" >
        <ContentTemplate>
            <asp:UpdatePanel ID="Updatepanel1" runat="server" UpdateMode="Conditional">
                <ContentTemplate>
                    <asp:PlaceHolder ID="PlaceHolder1" runat="server"></asp:PlaceHolder>
                </ContentTemplate>
            </asp:UpdatePanel>
        </ContentTemplate>
    </telerik:RadWindow>   
 
    </form>
</body>
</html>

code behind:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
 
namespace WIIIP.Admin.Users
{
    public partial class Test : System.Web.UI.Page
    {
        private TestControl TestControl { get; set; }
 
        protected void Page_Load(object sender, EventArgs e)
        {
            if (bool.Parse(IsTestControlLoaded.Value))
                LoadTestControl();
        }
 
        protected void Button1_Click(object sender, EventArgs e)
        {
            LoadTestControl();
            ScriptManager.RegisterStartupScript(this, GetType(), "Key", "openWinContentTemplate();", true);
            IsTestControlLoaded.Value = true.ToString();
        }
 
        protected void LoadTestControl()
        {
            TestControl = (TestControl)Page.LoadControl("TestControl.ascx");
            PlaceHolder1.Controls.Add(TestControl);
            TestControl.Complete += new EventHandler(testControl_Complete);
        }
 
        void testControl_Complete(object sender, EventArgs e)
        {
            Literal1.Text = TestControl.EnteredValue;
            ScriptManager.RegisterStartupScript(this, GetType(), "Key", "closeWindow();", true);
        }
    }
}


Test Control:

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="TestControl.ascx.cs" Inherits="WIIIP.Admin.Users.TestControl" %>
 
<telerik:RadTextBox ID="TextBox1" runat="server" CssClass="text-long" />
<asp:CustomValidator ID="CustomValidator1" ValidationGroup="window" ControlToValidate="TextBox1"  OnServerValidate="TextBox1_ServerValidate" runat="server" ErrorMessage="- required" Text="*" ValidateEmptyText="True" />
<asp:Button ValidationGroup="window" runat="server" ID="Button2" OnClick="Button2_Click" Text="Close RadWindow1." />

Test Control code behind:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
 
namespace WIIIP.Admin.Users
{
    public partial class TestControl : System.Web.UI.UserControl
    {
        public event EventHandler Complete;
 
        protected void Button2_Click(object sender, EventArgs e)
        {
            if (Page.IsValid)
            {
                Complete(this, null);
            }
        }
 
        protected void TextBox1_ServerValidate(object sender, ServerValidateEventArgs e)
        {
            e.IsValid = !string.IsNullOrEmpty(e.Value);
        }
 
        public string EnteredValue { get { return TextBox1.Text; } }
    }
}

0
Merritt
Top achievements
Rank 1
answered on 09 Mar 2012, 02:28 AM
What's going on?

The RadAjaxManager is used to hook up the PlaceHolder (where the control goes) and the Button (which fires the server event that will load the user control into the place holder and register the javscript that will open the rad window) and Literal (which shows what was entered in the text box within the user control).

You'll notice that the RadWindow's content template has an update panel in it. This allows for the content within the RadWindow to work properly and use ms ajax accordingly.

Also, to handle situations where the client clicks the X icon in the top right (bypassing the server code to close the rad window), i incorporated a hidden input that's value is changed during the javascript open and close events of the RadWindow. This allows the server code to properly load or not load the User Control depending on the current open/close state of the RadWindow.

My next step is incorporating this into a RadGrid and using a command column to open the window and allow some sort of function on the selected row that doesn't adhere to some strict structure of inser/edit. For instance, say the grid represented a list of contacts and you had a button on each row that when clicked would fire a sequence of events allowing the user to send an email to that particular contact. Instead of redirecting them to a new page (which is sometimes the better choice, but sometimes it just isn't) a modal popup would appear. 

Of course, one could say why not just use the Ajax Control Toolkit ModalPopup Extender? Guess what: I didn't want to because I have already done that and it presented no challenge (except for making sure it's styling matched that of the telerik tools).

So this is my solution for using RadWindow as I wanted to not as some iframe or simple confirm dialog. My goal is to use it like the Ajax Control Toolkit's Modal PopUp Extender.

Most Importantly: why is this all necessary? I don't know. I wanted this behavior:

http://demos.telerik.com/aspnet-ajax/window/examples/internalcontent/defaultcs.aspx 

But could not get it to work when I need to open and close the window using ajax. Moral of the story: everything is harder than you initially think it will be.
0
Marin Bratanov
Telerik team
answered on 09 Mar 2012, 02:56 PM
Hi Merritt,

I am sorry to hear that you are having difficulties in getting things to run as you wish. I believe you have already found the most important resources on using RadWindow with AJAX (i.e. this article and this sticky thread). Also, the demo you linked adheres to the guidelines the article provides - AJAX is applied to the controls inside the ContentTemplate, not to the entire RadWindow and I believe you can avoid the asp UpdatePanel you have in the ContentTemplate. Thus, I believe, the control has consistent behavior, although it may seem a little unexpected for people used to different toolkits.

Now, why is this move in the DOM needed - there are two simple reasons:
1) the entire RadWindow markup (i.e. its UI - borders, buttons, its entire behavior) is created on the fly with JavaScript. It is not present on the page otherwise which makes the page lighter and avoids server rendering
2) taking the content to where the markup is rendered (i.e. as a direct child of the form) means it can be shown correctly, as otherwise it may inherit styles from its parents that will prevent its visibility or position from working correctly. This approach allows it to handle even complex scenarios by making it more independent from its context, like a popup should be.

As for creating controls dynamically - this is considered general ASP knowledge and I can suggest you take a look at this article from the net as a starting point on working with dynamic controls. Said shortly - if they are not in the markup they will be lost after a postback (asynchronous or not) unless the developer takes steps to recreate them. This does not add a new instance, but (re-)creates it on each postback. Thus, it is a good practise that helps in handling viewstate, for example, to provide an ID to this control that will always be the same when you recreate it. It is also good to load the control in the page Init event.


Kind regards,
Marin
the Telerik team
If you want to get updates on new releases, tips and tricks and sneak peeks at our product labs directly from the developers working on the RadControls for ASP.NET AJAX, subscribe to their blog feed now.
0
Merritt
Top achievements
Rank 1
answered on 09 Mar 2012, 05:16 PM
You are right:

<telerik:RadWindow ID="RadWindow1" runat="server" Behaviors="Close" EnableShadow="true" Modal="true" OnClientClose="OnClientClose" >
        <ContentTemplate>
                    <asp:PlaceHolder ID="PlaceHolder1" runat="server"></asp:PlaceHolder>
        </ContentTemplate>
    </telerik:RadWindow>

Seems to work how i want it to.
Tags
Window
Asked by
Merritt
Top achievements
Rank 1
Answers by
Merritt
Top achievements
Rank 1
Marin Bratanov
Telerik team
Share this question
or