Using the ASP.NET UpdatePanel Control with User Controls

You can enable partial-page updates for user controls as you do for other controls on a Web page. You must add a ScriptManager control to the page and set its EnablePartialRendering property to true. The ScriptManager control will manage partial-page updates for UpdatePanel controls that are directly on the ASP.NET Web page or inside a user control on the page.

In a simple scenario, you can put user controls inside an update panel and they will be refreshed when the contents of the update panel are updated. You can also put an UpdatePanel control inside a user control so that the user control supports partial-page updates. However, in that case, page developers who add the user control to a page must explicitly add a ScriptManager control in the host Web page.

If you are programmatically adding controls to your user control, you can determine whether a ScriptManager control exists on the page. You can then make sure that the EnablePartialRendering property has been set to true before you add an UpdatePanel control to the user control. For an example that shows how to do this in a Web server control, see Using the ASP.NET UpdatePanel Control with Data-Bound Controls.

You might have multiple user controls on a Web page that you want to update independently. In that case, you can include one or more UpdatePanel controls inside the user control, and extend the user control to publicly expose the capabilities of the child UpdatePanel controls.

The example in this tutorial includes two user controls whose contents is inside UpdatePanel controls. Each user control exposes the UpdateMode property of the inner UpdatePanel control so that the property can be set explicitly for each user control. Each user control also exposes the Update method of the inner UpdatePanel control so that an external source can explicitly refresh the contents of the user control.

Creating an ASP.NET Web Page with Multiple User Controls

The example in this tutorial creates a master-detail page of employee information from the AdventureWorks sample database. One user control uses a GridView control to display a list of employee names and to support selecting, paging, and sorting. Another user control uses a DetailsView control to display details for a selected employee.

The employee-list user control stores the ID of the selected employee in view state. It makes sure that only the selected employee is highlighted in the GridView control, regardless of which page of data is displayed or of how the list has been sorted. The user control also makes sure that the employee-detail user control is displayed only when the selected employee is visible in the employee list.

In the example, the employee-detail user control contains an UpdatePanel control. The update panel is refreshed when an employee is selected. It is also refreshed when the user moves away from the GridView control page that displays the selected employee. If the user views a page of the GridView control that does not include the selected employee, the employee-detail user control is not displayed and the update panel is not updated.

Including an UpdatePanel Control in the User Control

The first step in creating the user controls that refresh independently is to include an UpdatePanel control in the user control, as shown in the following example.

<%@ Control Language="VB" AutoEventWireup="true" CodeFile="EmployeeInfo.ascx.vb" Inherits="EmployeeInfo" %>
<asp:UpdatePanel ID="EmployeeInfoUpdatePanel" runat="server">
  <ContentTemplate>
    <asp:Label ID="LastUpdatedLabel" runat="server"></asp:Label>
    <asp:DetailsView ID="EmployeeDetailsView" runat="server" Height="50px" Width="410px" AutoGenerateRows="False" BackColor="LightGoldenrodYellow" BorderColor="Tan" BorderWidth="1px" CellPadding="2" DataSourceID="EmployeeDataSource" ForeColor="Black" GridLines="None">
      <FooterStyle BackColor="Tan" />
      <EditRowStyle BackColor="DarkSlateBlue" ForeColor="GhostWhite" />
      <PagerStyle BackColor="PaleGoldenrod" ForeColor="DarkSlateBlue" HorizontalAlign="Center" />
      <Fields>
        <asp:BoundField DataField="LastName" HeaderText="Last Name" SortExpression="LastName" />
        <asp:BoundField DataField="FirstName" HeaderText="First Name" SortExpression="FirstName" />
        <asp:BoundField DataField="EmailAddress" HeaderText="E-mail Address" SortExpression="EmailAddress" />
        <asp:BoundField DataField="Phone" HeaderText="Phone" SortExpression="Phone" />
        <asp:BoundField DataField="HireDate" HeaderText="Hire Date" SortExpression="HireDate" />
        <asp:BoundField DataField="VacationHours" HeaderText="Vacation Hours" SortExpression="VacationHours" />
        <asp:BoundField DataField="SickLeaveHours" HeaderText="Sick Leave Hours" SortExpression="SickLeaveHours" />
      </Fields>
      <HeaderStyle BackColor="Tan" Font-Bold="True" />
      <AlternatingRowStyle BackColor="PaleGoldenrod" />
    </asp:DetailsView>
    <asp:SqlDataSource ID="EmployeeDataSource" runat="server" ConnectionString="<%$ ConnectionStrings:AdventureWorksConnectionString %>"
        SelectCommand="SELECT Person.Contact.LastName, Person.Contact.FirstName, Person.Contact.EmailAddress, Person.Contact.Phone, HumanResources.Employee.HireDate, HumanResources.Employee.VacationHours, HumanResources.Employee.SickLeaveHours FROM Person.Contact INNER JOIN HumanResources.Employee ON Person.Contact.ContactID = HumanResources.Employee.ContactID WHERE HumanResources.Employee.EmployeeID = @SelectedEmployeeID">
      <SelectParameters>
        <asp:Parameter Name="SelectedEmployeeID" />
      </SelectParameters>
    </asp:SqlDataSource>
  </ContentTemplate>
</asp:UpdatePanel>
<%@ Control Language="C#" AutoEventWireup="true" CodeFile="EmployeeInfo.ascx.cs" Inherits="EmployeeInfo" %>
<asp:UpdatePanel ID="EmployeeInfoUpdatePanel" runat="server">
  <ContentTemplate>
    <asp:Label ID="LastUpdatedLabel" runat="server"></asp:Label>
    <asp:DetailsView ID="EmployeeDetailsView" runat="server" Height="50px" Width="410px" AutoGenerateRows="False" BackColor="LightGoldenrodYellow" BorderColor="Tan" BorderWidth="1px" CellPadding="2" DataSourceID="EmployeeDataSource" ForeColor="Black" GridLines="None">
      <FooterStyle BackColor="Tan" />
      <EditRowStyle BackColor="DarkSlateBlue" ForeColor="GhostWhite" />
      <PagerStyle BackColor="PaleGoldenrod" ForeColor="DarkSlateBlue" HorizontalAlign="Center" />
      <Fields>
        <asp:BoundField DataField="LastName" HeaderText="Last Name" SortExpression="LastName" />
        <asp:BoundField DataField="FirstName" HeaderText="First Name" SortExpression="FirstName" />
        <asp:BoundField DataField="EmailAddress" HeaderText="E-mail Address" SortExpression="EmailAddress" />
        <asp:BoundField DataField="Phone" HeaderText="Phone" SortExpression="Phone" />
        <asp:BoundField DataField="HireDate" HeaderText="Hire Date" SortExpression="HireDate" />
        <asp:BoundField DataField="VacationHours" HeaderText="Vacation Hours" SortExpression="VacationHours" />
        <asp:BoundField DataField="SickLeaveHours" HeaderText="Sick Leave Hours" SortExpression="SickLeaveHours" />
      </Fields>
      <HeaderStyle BackColor="Tan" Font-Bold="True" />
      <AlternatingRowStyle BackColor="PaleGoldenrod" />
    </asp:DetailsView>
    <asp:SqlDataSource ID="EmployeeDataSource" runat="server" ConnectionString="<%$ ConnectionStrings:AdventureWorksConnectionString %>"
        SelectCommand="SELECT Person.Contact.LastName, Person.Contact.FirstName, Person.Contact.EmailAddress, Person.Contact.Phone, HumanResources.Employee.HireDate, HumanResources.Employee.VacationHours, HumanResources.Employee.SickLeaveHours FROM Person.Contact INNER JOIN HumanResources.Employee ON Person.Contact.ContactID = HumanResources.Employee.ContactID WHERE HumanResources.Employee.EmployeeID = @SelectedEmployeeID">
      <SelectParameters>
        <asp:Parameter Name="SelectedEmployeeID" />
      </SelectParameters>
    </asp:SqlDataSource>
  </ContentTemplate>
</asp:UpdatePanel>

Exposing the Capabilities of the UpdatePanel Control Publicly

The next step is to expose the UpdateMode property and the Update method of the inner UpdatePanel control. This enables you to set properties of the inner UpdatePanel control from outside the user control, as shown in the following example.

Public Property UpdateMode() As UpdatePanelUpdateMode
    Get
        Return Me.EmployeeInfoUpdatePanel.UpdateMode
    End Get
    Set(ByVal value As UpdatePanelUpdateMode)
        Me.EmployeeInfoUpdatePanel.UpdateMode = value
    End Set
End Property

Public Sub Update()
    Me.EmployeeInfoUpdatePanel.Update()
End Sub
public UpdatePanelUpdateMode UpdateMode
{
    get { return this.EmployeeInfoUpdatePanel.UpdateMode; }
    set { this.EmployeeInfoUpdatePanel.UpdateMode = value; }
}

public void Update()
{
    this.EmployeeInfoUpdatePanel.Update();
}

Adding the User Controls to the Web Page

You can now can add the user controls to an ASP.NET Web page and set the UpdateMode property of the inner UpdatePanel control declaratively. For this example, the UpdateMode property for both user controls is set to Conditional. This means that they are updated only when an update is explicitly requested, as shown in the following example.

<asp:ScriptManager ID="ScriptManager1" runat="server"
                   EnablePartialRendering="true" /> 
<table>
    <tr>
        <td valign="top">
            <uc2:EmployeeList ID="EmployeeList1" runat="server" UpdateMode="Conditional"
                              OnSelectedIndexChanged="EmployeeList1_OnSelectedIndexChanged" />
        </td>
        <td valign="top">
            <uc1:EmployeeInfo ID="EmployeeInfo1" runat="server" UpdateMode="Conditional" />
        </td>
    </tr>
</table>

<asp:ScriptManager ID="ScriptManager1" runat="server"
                   EnablePartialRendering="true" /> 
<table>
    <tr>
        <td valign="top">
            <uc2:EmployeeList ID="EmployeeList1" runat="server" UpdateMode="Conditional"
                              OnSelectedIndexChanged="EmployeeList1_OnSelectedIndexChanged" />
        </td>
        <td valign="top">
            <uc1:EmployeeInfo ID="EmployeeInfo1" runat="server" UpdateMode="Conditional" />
        </td>
    </tr>
</table>

Adding Code to Refresh the User Controls

To explicitly update the user control, you call the Update method of the inner UpdatePanel control. The following example includes a handler for the SelectedIndexChanged event of the employee-list user control, which is raised when the SelectedIndexChanged event of the inner GridView control is raised. The code in the handler explicitly updates the employee-details user control if an employee is selected, or if the current page in the employee list no longer shows the selected employee.

Protected Sub EmployeeList1_OnSelectedIndexChanged(sender As Object, e As EventArgs) 
    If EmployeeList1.SelectedIndex <> -1 Then 
        EmployeeInfo1.EmployeeID = EmployeeList1.EmployeeID 
    Else 
        EmployeeInfo1.EmployeeID = 0 
    End If 

    EmployeeInfo1.Update() 
End Sub 
protected void EmployeeList1_OnSelectedIndexChanged(object sender, EventArgs e)
{
    if (EmployeeList1.SelectedIndex != -1)
        EmployeeInfo1.EmployeeID = EmployeeList1.EmployeeID;
    else
        EmployeeInfo1.EmployeeID = 0;

    EmployeeInfo1.Update();
}

See Also

Concepts

UpdatePanel Control Overview

ASP.NET User Controls Overview

Reference

UpdatePanel

ScriptManager

Other Resources

UpdatePanel Control Tutorials