Hello,
I have a MasterPage defining the structural layout of my site with a left menu and content areas. In the content area I have an UpdatePanel that needs to update its controls when a button in the menu area is clicked. The button is outside the UpdatePanel so I tried specifying an AsyncPostBackTrigger but I got the following exception: A control with ID 'BtnNavigate' could not be found for the trigger in UpdatePanel 'PnlUpdate'. It seems that the button must be in the same naming container as the UpdatePanel for this to work.
I found a workaround for this problem by moving the real button in the same container as the UpdatePanel and hiding it with display: none. Then I put a dummy button in the menu area which just invokes the click event of the real button with some javascript. This works fine in IE but in Firefox a total PostBack is done when I click the button in the menu area.
Here's the code of a simple page that illustrates this behavior:
<%@dotnet.itags.org. Page Language="C#" MasterPageFile="~/Web/MasterPage.master" Title="Untitled Page" %><script runat="server"> protected void RealButton_Click(object sender, EventArgs e) { LblTest.Text = DateTime.Now.ToLongTimeString(); }</script><asp:Content ID="LeftNav" ContentPlaceHolderID="LeftNav" Runat="Server"> <input type="button" onclick="$get('<%= RealButton.ClientID %>').click();" value="Test" /></asp:Content><asp:Content ID="Content" ContentPlaceHolderID="Content" Runat="Server"> <ajax:ScriptManager ID="ScriptManager" runat="server" /> <ajax:UpdatePanel ID="up1" runat="server"> <ContentTemplate> <asp:Label ID="LblTest" runat="server" /> </ContentTemplate> <Triggers> <ajax:AsyncPostBackTrigger ControlID="RealButton" /> </Triggers> </ajax:UpdatePanel> <asp:Button ID="RealButton" runat="server" style="display: none;" OnClick="RealButton_Click" /> </asp:Content>
Any suggestions that could help me resolving this issue are welcome. Thanks for your time.
PS. I forgot to mention that I am using Ajax RC1.
Ok, I think I figured it out:
Using
<asp:Button ID="RealButton" runat="server" style="display: none;" OnClick="RealButton_Click" UseSubmitBehavior="false" />instead of
<asp:Button ID="RealButton" runat="server" style="display: none;" OnClick="RealButton_Click" />replaces the total PostBack in Firefox with an AsyncPostBack.
OK I've come up with a work around that I think is a bit nicer than the dummy button thing.
I've created a custom control called EventProxy in my project that has a public event EventProxied and a public method ProxyEvent(EventArgs e). For each control or User control event on your page that you want to use as an async postback trigger on an update panel in a different ConntentPlaceHolder, add an instance of EventProxy to the same ContentPlaceHolder the update panel is in and use that instance's EventProxied event as the async event. Then in the handler code for the control/user control event's on the page, call the appropriate EventProxy control's ProxyEvent() method. Example code:
EventProxy Control:
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
namespace PlanIt.Web.Controls
{
publicclassEventProxy :Control,IPostBackEventHandler
{
public EventProxy()
{ }
publicvoid RaisePostBackEvent(string eventArgument)
{ }
publiceventEventHandler<EventArgs> EventProxied;
protectedvirtualvoid OnEventProxy(EventArgs e)
{
if (this.EventProxied !=null)
{
this.EventProxied(this, e);
}
}
publicvoid ProxyEvent(EventArgs e)
{
OnEventProxy(e);
}
}
}
Page Markup:
<%@.PageLanguage="C#"MasterPageFile="~/PlanItMaster.Master"Theme="Standard"AutoEventWireup="true"CodeBehind="EventProxyExample.aspx.cs"Inherits="PlanIt.Web.EventProxyExample"%>
<%@.RegisterAssembly="PlanIt.Web"Namespace="PlanIt.Web.Controls"TagPrefix="PlanIt"%>
<%@.RegisterSrc="~/Controls/TripTitle.ascx"TagName="TripTitleControl"TagPrefix="PlanIt"%>
<%@.RegisterSrc="~/Controls/BudgetControl.ascx"TagName="BudgetControl"TagPrefix="PlanIt"%>
<asp:ContentID="Content1"ContentPlaceHolderID="cphLeftPane"runat="server">
<asp:UpdatePanelID="updTitle"runat="server"UpdateMode="Conditional"ChildrenAsTriggers="true">
<ContentTemplate>
<PlanIt:TripTitleControlID="planItTripTitle"runat="server"OnTripTitleChanged="planItTripTitle_TripTitleChanged"/>
</ContentTemplate>
</asp:UpdatePanel>
</asp:Content>
<asp:ContentID="Content2"ContentPlaceHolderID="cphRightPane"runat="server">
<asp:UpdatePanelID="updBudget"runat="server"UpdateMode="Conditional"ChildrenAsTriggers="true">
<ContentTemplate>
<PlanIt:BudgetControlID="planItBudgetControl"runat="server"/>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTriggerControlID="epTripTitleChanged"EventName="EventProxied"/>
</Triggers>
</asp:UpdatePanel>
<PlanIt:EventProxyID="epTripTitleChanged"runat="server"/>
</asp:Content>
Page Code Behind:
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
namespace PlanIt.Web
{
publicpartialclassEventProxyExample : System.Web.UI.Page
{
protectedvoid Page_Load(object sender,EventArgs e)
{ }
protectedvoid planItTripTitle_TripTitleChanged(object sender, TripTitleChangedEventArgs e)
{
epTripTitleChanged.ProxyEvent(e);
// force a refresh of the budget control
planItBudgetControl.Refresh();
}
}
}
Cheers,
D.
No comments:
Post a Comment