Geeks With Blogs
Amit's Blog Sharing Thoughts and Learning

In this post, I will show you how to load different user control in UpdatePanel from different menu item click. I have found a lot of request in Asp.net Ajax Forum and some of them are having misconception about this. Once you complete reading this post you will be able to load controls dynamically and learn how to employ different helper controls like UpdateProgress, ModalPopupExtender while the UserControl is loading. First let us create plain page without the ajax support:

Markup:

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="PlainSampleMenu.aspx.cs" Inherits="PlainSampleMenuPage" %>
<!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>Plain Sample Menu</title>
</head>
<body>
    <form id="form1" runat="server">
        <asp:Menu ID="Menu1" runat="server" OnMenuItemClick="Menu1_MenuItemClick">
            <Items>
                <asp:MenuItem Text="File">
                    <asp:MenuItem Text="Load Control1"></asp:MenuItem>
                    <asp:MenuItem Text="Load Control2"></asp:MenuItem>
                    <asp:MenuItem Text="Load Control3"></asp:MenuItem>
                </asp:MenuItem>
            </Items>
        </asp:Menu>
        <br />
        <br />
        <asp:PlaceHolder ID="PlaceHolder1" runat="server"></asp:PlaceHolder>
    </form>
</body>
</html>

Code Behind:

using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

public partial class PlainSampleMenuPage : System.Web.UI.Page
{
    private const string BASE_PATH = "~/DynamicControlLoading/";

    private string LastLoadedControl
    {
        get
        {
            return ViewState["LastLoaded"] as string;
        }
        set
        {
            ViewState["LastLoaded"] = value;
        }
    }

    private void LoadUserControl()
    {
        string controlPath = LastLoadedControl;

        if (!string.IsNullOrEmpty(controlPath))
        {
            PlaceHolder1.Controls.Clear();
            UserControl uc = (UserControl)LoadControl(controlPath);
            PlaceHolder1.Controls.Add(uc);
        }
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        LoadUserControl();
    }

    protected void Menu1_MenuItemClick(object sender, MenuEventArgs e)
    {
        MenuItem menu = e.Item;

        string controlPath = string.Empty;

        switch (menu.Text)
        {
            case "Load Control2":
                controlPath = BASE_PATH + "SampleControl2.ascx";
                break;
            case "Load Control3":
                controlPath = BASE_PATH + "SampleControl3.ascx";
                break;
            default:
                controlPath = BASE_PATH + "SampleControl1.ascx";
                break;
        }

        LastLoadedControl = controlPath;
        LoadUserControl();
    }
}

As you can see we are loading the UserControls in the PlaceHolder Control on different menu item click. If you are wondering why I am also loading the controls in Page Load event based upon the ViewState, the reason is otherwise those dynamically loaded controls will not be visible in the consequent postbacks. There are few good articles written by Scott Mitchell on dynamically loading Controls which you will find in the following links:

Now let us ajaxify this page, lets wrap the PlaceHolder with an UpdatePanel control. The following shows the markup:

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="SampleMenu1.aspx.cs" Inherits="SampleMenuPage1" %>
<!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>Sample Menu</title>
</head>
<body>
    <form id="form1" runat="server">
        <asp:Menu ID="Menu1" runat="server" OnMenuItemClick="Menu1_MenuItemClick">
            <Items>
                <asp:MenuItem Text="File">
                    <asp:MenuItem Text="Load Control1"></asp:MenuItem>
                    <asp:MenuItem Text="Load Control2"></asp:MenuItem>
                    <asp:MenuItem Text="Load Control3"></asp:MenuItem>
                </asp:MenuItem>
            </Items>
        </asp:Menu>
        <br />
        <br />
        <asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
        <asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional">
            <ContentTemplate>
                <asp:PlaceHolder ID="PlaceHolder1" runat="server"></asp:PlaceHolder>
            </ContentTemplate>
            <Triggers>
                <asp:AsyncPostBackTrigger ControlID="Menu1" />
            </Triggers>
        </asp:UpdatePanel>
    </form>
</body>
</html>

Since the Menu control resides outside the UpdatePanel we will also need a AsyncPostBackTrigger for the Menu Control. Now run this page, you will find the controls are loaded without a full postback.

Now let us further enhance this page with UpdateProgress and AjaxControlToolKit's ModalPopupExtender. First with the UpdateProgress Control.

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="SampleMenu1.aspx.cs" Inherits="SampleMenuPage1" %>
<!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>Sample Menu - UpdateProgress</title>
</head>
<body>
    <form id="form1" runat="server">
        <asp:Menu ID="Menu1" runat="server" OnMenuItemClick="Menu1_MenuItemClick">
            <Items>
                <asp:MenuItem Text="File">
                    <asp:MenuItem Text="Load Control1"></asp:MenuItem>
                    <asp:MenuItem Text="Load Control2"></asp:MenuItem>
                    <asp:MenuItem Text="Load Control3"></asp:MenuItem>
                </asp:MenuItem>
            </Items>
        </asp:Menu>
        <br />
        <br />
        <asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
        <asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional">
            <ContentTemplate>
                <asp:UpdateProgress ID="UpdateProgress1" runat="server" AssociatedUpdatePanelID="UpdatePanel1">
                    <ProgressTemplate>
                        Loading....
                    </ProgressTemplate>
                </asp:UpdateProgress>
                <asp:PlaceHolder ID="PlaceHolder1" runat="server"></asp:PlaceHolder>
            </ContentTemplate>
            <Triggers>
                <asp:AsyncPostBackTrigger ControlID="Menu1" />
            </Triggers>
        </asp:UpdatePanel>
    </form>
</body>
</html>

As you can see we have added a UpdateProgress Control in the UpdatePanel ContentTemplate. But the UpdateProgress does not get visible when you click any of the menu item. This is the true nature of UpdatePanel, it does not shows the UpdateProgress if the control is out side the UpdatePanel which caused the postback. We have to manually show the UpdateProgress by the JavaScript code like the following:

<script type="text/javascript">

    var prm = Sys.WebForms.PageRequestManager.getInstance();

    prm.add_initializeRequest(initializeRequest);
    prm.add_endRequest(endRequest);

    var _postBackElement;

    function initializeRequest(sender, e)
    {
        if (prm.get_isInAsyncPostBack())
        {
            e.set_cancel(true);
        }

        _postBackElement = e.get_postBackElement();

        if (_postBackElement.id.indexOf('Menu1') > -1)
        {
            $get('UpdateProgress1').style.display = 'block';
        }
    }

    function endRequest(sender, e)
    {
        if (_postBackElement.id.indexOf('Menu1') > -1)
        {
            $get('UpdateProgress1').style.display = 'none';
        }
    }
</script>

Now run the page, you will find the UpdateProgress Control is showing the loading message no matter which control caused the postback.

In this final section we will implement the AjaxControlToolKit's ModalPopupExtender to show the loading message, this will give you a similar look of CodePlex Site. The following shows the source:

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="SampleMenu2.aspx.cs" Inherits="SampleMenuPage2" %>
<!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>Sample Menu - ModalPopupExtender</title>
    <style type="text/css">
        .modalBackground
        {
            background-color:#dcdcdc;
            filter:alpha(opacity=60);
            opacity:0.60;
        }
    </style>
</head>
<body>
    <form id="form1" runat="server">
        <asp:Menu ID="Menu1" runat="server" OnMenuItemClick="Menu1_MenuItemClick">
            <Items>
                <asp:MenuItem Text="File">
                    <asp:MenuItem Text="Load Control1"></asp:MenuItem>
                    <asp:MenuItem Text="Load Control2"></asp:MenuItem>
                    <asp:MenuItem Text="Load Control3"></asp:MenuItem>
                </asp:MenuItem>
            </Items>
        </asp:Menu>
        <br />
        <br />
        <asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
        <asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional">
            <ContentTemplate>
                <asp:PlaceHolder ID="PlaceHolder1" runat="server"></asp:PlaceHolder>
            </ContentTemplate>
            <Triggers>
                <asp:AsyncPostBackTrigger ControlID="Menu1" />
            </Triggers>
        </asp:UpdatePanel>
        <asp:Panel ID="Panel1" runat="server" style="background-color:#ffffff;display:none;width:400px">
            <div style="padding:8px">
                <h2>Loading...</h2>
            </div>
        </asp:Panel>
        <ajaxToolKit:ModalPopupExtender ID="ModalPopupExtender1" runat="server" TargetControlID="Panel1" PopupControlID="Panel1" BackgroundCssClass="modalBackground" DropShadow="true" />
        <script type="text/javascript">

            var prm = Sys.WebForms.PageRequestManager.getInstance();

            prm.add_initializeRequest(initializeRequest);
            prm.add_endRequest(endRequest);

            var _postBackElement;

            function initializeRequest(sender, e)
            {
                if (prm.get_isInAsyncPostBack())
                {
                    e.set_cancel(true);
                }

                _postBackElement = e.get_postBackElement();

                if (_postBackElement.id.indexOf('Menu1') > -1)
                {
                    $find('ModalPopupExtender1').show();
                }
            }

            function endRequest(sender, e)
            {
                if (_postBackElement.id.indexOf('Menu1') > -1)
                {
                    $find('ModalPopupExtender1').hide();
                }
            }
        </script>
    </form>
</body>
</html>

As you can see we first created a custom style which will be shown as the background style when the modal popup is visible, next we have added a regular Asp.net Panel control which will be shown as the modal popup. We have initially set the Panel control display mode to none, so there will be no flicker when the modal popup is shown. At last, we have added a ModalPopupExtender and sets its required property. The previous rule also applies here, we have to manually show/hide the ModalPopup which we are doing in the above JavaScript code. You will also found few cool techniques of ModalPopupExtender in this link.

To run the sample first create a AjaxControlToolKit enable site website then create a folder DynamicControlLoading folder and copy the files in the following attachment.

Download: Complete Source

kick it on DotNetKicks.com

Posted on Saturday, August 11, 2007 8:48 PM Asp.net Ajax , Tips/Tricks | Back to top


Comments on this post: Loading UserControl Dynamically in UpdatePanel

# re: Loading UserControl Dynamically in UpdatePanel
Requesting Gravatar...
Hi,

I tried using UpdatePanel code...
Things work fine. But when I debug, I see the PageLoad event being fired twice...

Is this the nature of the UpdatePanel control?

Thanks,
Sridhar
Left by Sridhar Bommana on Aug 16, 2007 2:37 PM

# re: Loading UserControl Dynamically in UpdatePanel
Requesting Gravatar...
yes the pageload event in the client side fires for every asyncpostback.
Left by Kazi Manzur Rashid on Aug 16, 2007 4:50 PM

# re: Loading UserControl Dynamically in UpdatePanel
Requesting Gravatar...
i've got some yui javascript in SampleControl2.ascx but it doesn't fire. it'll fire if i put it in the default controls' prm.add_pageLoaded function.

what do i need to do?
Left by afromobile on Aug 16, 2007 10:23 PM

# re: Loading UserControl Dynamically in UpdatePanel
Requesting Gravatar...
Hi,
If your usercontrol includes any TextBoxes or other controls with postback data, you will not be able to use these values immediately in the Page_Load. Unfortunatelly, in large applications in may be very significant problem. To overcome this problem it is better during postback to load user control in overridden LoadViewState method after calling base.LoadViewState. In this case you do load it before postback data are handled and user control comes loaded to Page_load event.
Left by Yuriy on Aug 20, 2007 3:27 AM

# re: Loading UserControl Dynamically in UpdatePanel
Requesting Gravatar...
Thanks for pointing out this Yuriy.
Left by Kazi Manzur Rashid on Aug 20, 2007 3:36 AM

# re: Loading UserControl Dynamically in UpdatePanel
Requesting Gravatar...
Hi,

Nice article, but I was wondering what do i need to do if I'm trying to load multiple user control in one event? Can you help me out? co'z it's not working i'm getting an error:

Failed to load viewstate. The control tree into which viewstate is being loaded must match the control tree that was used to save viewstate during the previous request. For example, when adding controls dynamically, the controls added during a post-back must match the type and position of the controls added during the initial request.

Left by Sidney on Oct 01, 2007 12:04 AM

# re: Loading UserControl Dynamically in UpdatePanel
Requesting Gravatar...
Article was very useful,
However it is missing important line of code:
in the LoadUserControl() method you need to set the control ID or you will be loosing postbacks within user controls
e.g.
UserControl uc = (UserControl)LoadControl(controlPath);
uc.ID = "dummyID";

Thanks
Left by waflarz on Dec 11, 2007 7:03 AM

# re: Loading UserControl Dynamically in UpdatePanel
Requesting Gravatar...
Nice example, Helps a lot. Thanks man
Left by Ashraf on Jan 07, 2008 1:06 PM

# re: Loading UserControl Dynamically in UpdatePanel
Requesting Gravatar...
This article really helped out a lot. Thanks.
Left by vinyl outdoor shutters on Jan 31, 2008 3:25 AM

# re: Loading UserControl Dynamically in UpdatePanel
Requesting Gravatar...
vary good sample thanks man`

But I notice one thing, if you are click on menu item and load sample1 ascx then click on submit event is fired...but...if you again click from menu and load again sample1 ascx and then click submit event will not fire...but it will fire second time when you click submit again...
How to solve this???

Thanks...
Left by SCSI on Mar 26, 2008 1:01 AM

# re: Loading UserControl Dynamically in UpdatePanel
Requesting Gravatar...
Hello
Ok the pageload event in the client side fires for every Thank you
Left by tv izle on Apr 17, 2008 2:05 AM

# re: Loading UserControl Dynamically in UpdatePanel
Requesting Gravatar...
Nice topic , it really help me a lot.
But is there any way i.e. to use javascript to load the user controls at the first time.
if possible please help me

Left by vaskar on May 30, 2008 1:19 PM

# re: Loading UserControl Dynamically in UpdatePanel
Requesting Gravatar...
its a nice article..but can you tell me how to render samplecontrol1 4-5 times in a single page? like if i click 5 times on tree view 'Load Control 1' and it will show samplecontrol1 5 times?
Left by Faisal on Jul 02, 2008 2:18 PM

# re: Loading UserControl Dynamically in UpdatePanel
Requesting Gravatar...
Is there an easy way to dynamically load a user control without the controls (inside the user control) becoming ajaxified? All of the controls inside my user control are all updating each other on every postback. Any help would be greatly appreciated.
Left by Professional-Icons on Aug 18, 2008 10:04 PM

# re: Loading UserControl Dynamically in UpdatePanel
Requesting Gravatar...
For SCSI : it is due to the use of a dynamically added trigger in the Page.Load event.
You need to put the declaration of this trigger in the Page.Init if you want it to work everytime.
I had this problem before but since I do all in Page.Init it works perfectly.
Left by Micael on Aug 25, 2008 8:48 PM

# re: Loading UserControl Dynamically in UpdatePanel
Requesting Gravatar...
Very useful blogpost. Saved me some time... Thanks!
Left by Peter on Sep 22, 2008 2:58 PM

# re: Loading UserControl Dynamically in UpdatePanel
Requesting Gravatar...
Hi SCSI

I ran into the same problem and solve it.
event handler won't register if you add your controls in page_load. add them in page_init instead.

you can see the post in my blog : maxi326.wordpress.com
Left by Maxi on Oct 03, 2008 11:08 AM

# re: Loading UserControl Dynamically in UpdatePanel
Requesting Gravatar...
Hello!

How to do when I want a Selected Menu Item? Let say I have five User Controls. When i load the page none of them is selected from the start, how do i select a User Control that dynamicly load in on Page_Load?

Thanks!
Left by Peter on Oct 29, 2008 8:59 PM

# re: Loading UserControl Dynamically in UpdatePanel
Requesting Gravatar...
There seems to be a bug.

If you press control2 in the menu THEN use f5 to refresh the browser you lose the page you are on but on top of that you also wont be able to load any control at all.

trying to figure out a fix for it but havent found one yet..
Left by yen on Nov 11, 2008 5:46 AM

Your comment:
 (will show your gravatar)
 


Copyright © Kazi Manzur Rashid | Powered by: GeeksWithBlogs.net | Join free