Using the ASP.NET UpdatePanel Control with Data-Bound Controls
You can create a richer user experience in your AJAX-enabled ASP.NET applications by using partial-page rendering. Partial-page rendering removes the need for the whole page to refresh as the result of a postback. Instead, you can specify only the region of the page to be refreshed. As a result, users no longer see the whole page reload with every postback.
This topic assumes that you are familiar with the UpdatePanel control. If not, review the following topics:
You can enable partial-page rendering by using the UpdatePanel and ScriptManager Web server controls. The UpdatePanel control identifies a region of a page that can be updated. The ScriptManager control keeps track of the UpdatePanel controls that are on a page and the controls that trigger the UpdatePanel controls to refresh. Controls inside an UpdatePanel control that cause a postback are automatically identified as triggers for the update panel. You can also specify controls that are controls outside an UpdatePanel control. External triggers can be child controls of another UpdatePanel control. For more information, see Partial-Page Rendering Overview and UpdatePanel Control Overview.
This topic contains the following:
There is no limit to the number of UpdatePanel controls that you can put on a page. As a result, you can specify regions of a page that are refreshed independently of the whole page and independently of each other.
By default, the UpdateMode property of an UpdatePanel control is set to Always. This means that whenever a partial-page refresh is triggered, the UpdatePanel control refreshes the page, even if the trigger was not for that UpdatePanel control. To make sure that the UpdatePanel control is refreshed only when it has been triggered, you can set the UpdateMode property of the UpdatePanel control to Conditional.
The following example includes two UpdatePanel controls. One control includes Web controls that accept user input, and the other control displays what the user enters. Each UpdatePanel control has its UpdateMode property set to Conditional. As a result, if a user clicks the Cancel button to clear the fields of the input form, only the input form of the UpdatePanel control is refreshed. If a user clicks the Insert button to submit the form, both UpdatePanel controls are refreshed.
<%@ Page Language="VB" %> <%@ Import Namespace="System.Collections.Generic" %> <!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 id="Head1" runat="server"> <title>Enter New Employees</title> <script runat="server"> Private EmployeeList As List(Of Employee) Protected Sub Page_Load() If Not IsPostBack Then EmployeeList = New List(Of Employee) EmployeeList.Add(New Employee(1, "Jump", "Dan")) EmployeeList.Add(New Employee(2, "Kirwan", "Yvette")) ViewState("EmployeeList") = EmployeeList Else EmployeeList = CType(ViewState("EmployeeList"), List(Of Employee)) End If EmployeesGridView.DataSource = EmployeeList EmployeesGridView.DataBind() End Sub Protected Sub InsertButton_Click(ByVal sender As Object, ByVal e As EventArgs) If String.IsNullOrEmpty(FirstNameTextBox.Text) Or _ String.IsNullOrEmpty(LastNameTextBox.Text) Then Return Dim employeeID As Integer = EmployeeList(EmployeeList.Count - 1).EmployeeID + 1 Dim lastName As String = Server.HtmlEncode(FirstNameTextBox.Text) Dim firstName As String = Server.HtmlEncode(LastNameTextBox.Text) FirstNameTextBox.Text = String.Empty LastNameTextBox.Text = String.Empty EmployeeList.Add(New Employee(employeeID, lastName, firstName)) ViewState("EmployeeList") = EmployeeList EmployeesGridView.DataBind() EmployeesGridView.PageIndex = EmployeesGridView.PageCount End Sub Protected Sub CancelButton_Click(ByVal sender As Object, ByVal e As EventArgs) FirstNameTextBox.Text = String.Empty LastNameTextBox.Text = String.Empty End Sub <Serializable()> _ Public Class Employee Private _employeeID As Integer Private _lastName As String Private _firstName As String Public ReadOnly Property EmployeeID() As Integer Get Return _employeeID End Get End Property Public ReadOnly Property LastName() As String Get Return _lastName End Get End Property Public ReadOnly Property FirstName() As String Get Return _firstName End Get End Property Public Sub New(ByVal employeeID As Integer, ByVal lastName As String, ByVal firstName As String) _employeeID = employeeID _lastName = lastName _firstName = firstName End Sub End Class </script> </head> <body> <form id="form1" runat="server"> <div> </div> <asp:ScriptManager ID="ScriptManager1" runat="server" EnablePartialRendering="true" /> <table> <tr> <td style="height: 206px" valign="top"> <asp:UpdatePanel ID="InsertEmployeeUpdatePanel" runat="server" UpdateMode="Conditional"> <ContentTemplate> <table cellpadding="2" border="0" style="background-color:#7C6F57"> <tr> <td><asp:Label ID="FirstNameLabel" runat="server" AssociatedControlID="FirstNameTextBox" Text="First Name" ForeColor="White" /></td> <td><asp:TextBox runat="server" ID="FirstNameTextBox" /></td> </tr> <tr> <td><asp:Label ID="LastNameLabel" runat="server" AssociatedControlID="LastNameTextBox" Text="Last Name" ForeColor="White" /></td> <td><asp:TextBox runat="server" ID="LastNameTextBox" /></td> </tr> <tr> <td></td> <td> <asp:LinkButton ID="InsertButton" runat="server" Text="Insert" OnClick="InsertButton_Click" ForeColor="White" /> <asp:LinkButton ID="Cancelbutton" runat="server" Text="Cancel" OnClick="CancelButton_Click" ForeColor="White" /> </td> </tr> </table> <asp:Label runat="server" ID="InputTimeLabel"><%=DateTime.Now %></asp:Label> </ContentTemplate> </asp:UpdatePanel> </td> <td style="height: 206px" valign="top"> <asp:UpdatePanel ID="EmployeesUpdatePanel" runat="server" UpdateMode="Conditional"> <ContentTemplate> <asp:GridView ID="EmployeesGridView" runat="server" BackColor="LightGoldenrodYellow" BorderColor="Tan" BorderWidth="1px" CellPadding="2" ForeColor="Black" GridLines="None" AutoGenerateColumns="False"> <FooterStyle BackColor="Tan" /> <SelectedRowStyle BackColor="DarkSlateBlue" ForeColor="GhostWhite" /> <PagerStyle BackColor="PaleGoldenrod" ForeColor="DarkSlateBlue" HorizontalAlign="Center" /> <HeaderStyle BackColor="Tan" Font-Bold="True" /> <AlternatingRowStyle BackColor="PaleGoldenrod" /> <Columns> <asp:BoundField DataField="EmployeeID" HeaderText="Employee ID" /> <asp:BoundField DataField="LastName" HeaderText="Last Name" /> <asp:BoundField DataField="FirstName" HeaderText="First Name" /> </Columns> <PagerSettings PageButtonCount="5" /> </asp:GridView> <asp:Label runat="server" ID="ListTimeLabel"><%=DateTime.Now %></asp:Label> </ContentTemplate> <Triggers> <asp:AsyncPostBackTrigger ControlID="InsertButton" EventName="Click" /> </Triggers> </asp:UpdatePanel> </td> </tr> </table> </form> </body> </html>
You can also nest an UpdatePanel control inside another UpdatePanel control. If you set the UpdateMode property of both the outer and nested controls to Conditional, the outer panel is not refreshed when only the inner panel is triggered. However, if a trigger refreshes the outer panel, both the outer and inner panels are refreshed.
The following example includes a GridView control inside an UpdatePanel control. Each row of the GridView control contains a nested GridView control that is inside a child UpdatePanel control. When a new page of records is requested from an inner GridView control, the page regions of the outer panel and the panels in the other rows of the outer GridView control are not refreshed. When the outer GridView control displays a new page of records, the page regions of the outer panel and of the nested panels are all refreshed.
<%@ Page Language="VB" %> <!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>Browse Departments</title> <script runat="server"> Protected Sub DepartmentsGridView_RowDataBound(sender As object, e As GridViewRowEventArgs) If e.Row.RowType = DataControlRowType.DataRow Then Dim s As SqlDataSource = CType(e.Row.FindControl("EmployeesDataSource"), SqlDataSource) Dim r As System.Data.DataRowView = CType(e.Row.DataItem, System.Data.DataRowView) s.SelectParameters("DepartmentID").DefaultValue = r("DepartmentID").ToString() End If End Sub </script> </head> <body> <form id="form1" runat="server"> <div> <asp:ScriptManager runat="server" ID="ScriptManager1" EnablePartialRendering="true" /> <asp:UpdatePanel ID="UpdatePanel2" runat="server" UpdateMode="Conditional"> <ContentTemplate> <asp:GridView ID="DepartmentsGridView" runat="server" AllowPaging="True" AllowSorting="True" AutoGenerateColumns="False" CellPadding="4" DataSourceID="DepartmentDataSource" ForeColor="#333333" GridLines="None" PageSize="3" OnRowDataBound="DepartmentsGridView_RowDataBound"> <FooterStyle BackColor="#5D7B9D" Font-Bold="True" ForeColor="White" /> <Columns> <asp:BoundField DataField="GroupName" HeaderText="Division" SortExpression="GroupName" > <ItemStyle Width="200px" /> </asp:BoundField> <asp:BoundField DataField="Name" HeaderText="Department Name" SortExpression="Name" > <ItemStyle Width="160px" /> </asp:BoundField> <asp:TemplateField HeaderText="Employees"> <ItemTemplate> <asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional"> <ContentTemplate> <asp:GridView ID="EmployeesGridView" runat="server" AllowPaging="True" AllowSorting="True" AutoGenerateColumns="False" BackColor="White" BorderColor="#999999" BorderStyle="None" BorderWidth="1px" CellPadding="3" DataSourceID="EmployeesDataSource" GridLines="Vertical" PageSize="4"> <FooterStyle BackColor="#CCCCCC" ForeColor="Black" /> <Columns> <asp:BoundField DataField="FirstName" HeaderText="First Name" SortExpression="FirstName" > <ItemStyle Width="80px" /> </asp:BoundField> <asp:BoundField DataField="LastName" HeaderText="Last Name" SortExpression="LastName" > <ItemStyle Width="160px" /> </asp:BoundField> </Columns> <RowStyle BackColor="#EEEEEE" ForeColor="Black" /> <SelectedRowStyle BackColor="#008A8C" Font-Bold="True" ForeColor="White" /> <PagerStyle BackColor="#999999" ForeColor="Black" HorizontalAlign="Center" /> <HeaderStyle BackColor="#000084" Font-Bold="True" ForeColor="White" /> <AlternatingRowStyle BackColor="Gainsboro" /> </asp:GridView> <asp:Label runat="server" ID="InnerTimeLabel"><%=DateTime.Now %></asp:Label> <asp:SqlDataSource ID="EmployeesDataSource" runat="server" ConnectionString="<%$ ConnectionStrings:AdventureWorksConnectionString %>" SelectCommand="SELECT HumanResources.EmployeeDepartmentHistory.DepartmentID, HumanResources.vEmployee.EmployeeID, HumanResources.vEmployee.FirstName, HumanResources.vEmployee.LastName FROM HumanResources.EmployeeDepartmentHistory INNER JOIN HumanResources.vEmployee ON HumanResources.EmployeeDepartmentHistory.EmployeeID = HumanResources.vEmployee.EmployeeID WHERE HumanResources.EmployeeDepartmentHistory.DepartmentID = @DepartmentID ORDER BY HumanResources.vEmployee.LastName ASC, HumanResources.vEmployee.FirstName ASC"> <SelectParameters> <asp:Parameter Name="DepartmentID" DefaultValue="0" Type="int32" /> </SelectParameters> </asp:SqlDataSource> </ContentTemplate> </asp:UpdatePanel> </ItemTemplate> <ItemStyle Height="170px" Width="260px" /> </asp:TemplateField> </Columns> <RowStyle BackColor="#F7F6F3" ForeColor="#333333" VerticalAlign="Top" /> <EditRowStyle BackColor="#999999" /> <SelectedRowStyle BackColor="#E2DED6" Font-Bold="True" ForeColor="#333333" /> <PagerStyle BackColor="#284775" ForeColor="White" HorizontalAlign="Center" /> <HeaderStyle BackColor="#5D7B9D" Font-Bold="True" ForeColor="White" HorizontalAlign="Left" /> <AlternatingRowStyle BackColor="White" ForeColor="#284775" VerticalAlign="Top" /> </asp:GridView> <asp:Label runat="server" ID="OuterTimeLabel"><%=DateTime.Now %></asp:Label> </ContentTemplate> </asp:UpdatePanel> <asp:SqlDataSource ID="DepartmentDataSource" runat="server" ConnectionString="<%$ ConnectionStrings:AdventureWorksConnectionString %>" SelectCommand="SELECT DepartmentID, Name, GroupName FROM HumanResources.Department ORDER BY Name"> </asp:SqlDataSource> </div> </form> </body> </html>
Controls inside an UpdatePanel control that cause a postback are automatically configured as triggers for that UpdatePanel control. However, you might want to disable the automatic triggers and trigger a refresh of the UpdatePanel control from an external control only. To do this, set the ChildrenAsTriggers property of the UpdatePanel control to false. Then set the UpdateMode property of the UpdatePanel control to Conditional. These property settings will cause a refresh of the panel only if triggered an external control or by a call to the Update method.
The following example displays the categories, subcategories, and names of products from the AdventureWorks sample database. The category list rarely changes and there is no need to refresh the list of categories every time that a list of subcategories or products is displayed. Therefore, in the UpdatePanel control that contains the category list, you can set the ChildrenAsTriggers property to false and the UpdateMode property to Conditional. This makes sure that the UpdatePanel control refreshes only when explicitly requested.
<%@ Page Language="VB" AutoEventWireup="true" %> <!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>UpdatePanel Example</title> <script runat="server"> Protected Sub ProductsUpdatePanel_Load(sender As Object, e As EventArgs) CategoryTimeLabel.Text = DateTime.Now.ToString() End Sub Protected Sub CategoriesRepeater_ItemCommand(sender As Object, e As RepeaterCommandEventArgs) SubcategoriesDataSource.SelectParameters("CategoryID").DefaultValue = e.CommandArgument.ToString() SubcategoriesRepeater.DataBind() ProductsDataSource.SelectParameters("SubcategoryID").DefaultValue = "0" ProductsGridView.DataBind() End Sub Protected Sub SubcategoriesRepeater_ItemCommand(sender As Object, e As RepeaterCommandEventArgs) ProductsDataSource.SelectParameters("SubcategoryID").DefaultValue = e.CommandArgument.ToString() ProductsGridView.DataBind() End Sub Protected Sub RefreshCategoriesButton_Click(sender As Object, e As EventArgs) SubcategoriesDataSource.SelectParameters("CategoryID").DefaultValue = "0" SubcategoriesRepeater.DataBind() ProductsDataSource.SelectParameters("SubcategoryID").DefaultValue = "0" ProductsGridView.DataBind() End Sub </script> </head> <body> <form id="form1" runat="server"> <div> <asp:ScriptManager ID="ScriptManager1" runat="server"> </asp:ScriptManager> <table> <tr> <td valign="top" style="width:120px"> <asp:UpdatePanel ID="ProductsUpdatePanel" runat="server" ChildrenAsTriggers="False" OnLoad="ProductsUpdatePanel_Load" UpdateMode="Conditional"> <ContentTemplate> <asp:Repeater ID="CategoryRepeater" runat="server" DataSourceID="CategoriesDataSource" OnItemCommand="CategoriesRepeater_ItemCommand"> <ItemTemplate> <asp:LinkButton runat="server" ID="SelectCategoryButton" Text='<%# Eval("Name") %>' CommandName="SelectCategory" CommandArgument='<%#Eval("ProductCategoryID") %>' /><br /> </ItemTemplate> </asp:Repeater> <asp:SqlDataSource ID="CategoriesDataSource" runat="server" ConnectionString="<%$ ConnectionStrings:AdventureWorksConnectionString %>" SelectCommand="SELECT Name, ProductCategoryID FROM Production.ProductCategory ORDER BY ProductCategoryID"> </asp:SqlDataSource> <br /> <asp:Label ID="CategoryTimeLabel" runat="server" Text="Label" Font-Size="Smaller"></asp:Label> </ContentTemplate> <Triggers> <asp:AsyncPostBackTrigger ControlID="RefreshCategoriesButton" EventName="Click" /> </Triggers> </asp:UpdatePanel> <asp:LinkButton runat="Server" ID="RefreshCategoriesButton" Text="Refresh Category List" OnClick="RefreshCategoriesButton_Click" Font-Size="smaller" /> </td> <td valign="top"> <asp:UpdatePanel ID="SubcategoriesUpdatePanel" runat="server"> <ContentTemplate> <asp:Repeater ID="SubcategoriesRepeater" runat="server" DataSourceID="SubcategoriesDataSource" OnItemCommand="SubcategoriesRepeater_ItemCommand" > <ItemTemplate> <asp:LinkButton runat="server" ID="SelectSubcategoryButton" Text='<%# Eval("Name") %>' CommandName="SelectSubcategory" CommandArgument='<%#Eval("ProductSubcategoryID") %>' /><br /> </ItemTemplate> </asp:Repeater> <asp:SqlDataSource ID="SubcategoriesDataSource" runat="server" ConnectionString="<%$ ConnectionStrings:AdventureWorksConnectionString %>" SelectCommand="SELECT Name, ProductSubcategoryID FROM Production.ProductSubcategory WHERE Production.ProductSubcategory.ProductCategoryID = @CategoryID ORDER BY Name"> <SelectParameters> <asp:Parameter Name="CategoryID" DefaultValue="0" /> </SelectParameters> </asp:SqlDataSource> </ContentTemplate> </asp:UpdatePanel> </td> <td valign="top"> <asp:UpdatePanel ID="ProductUpdatePanel" runat="server"> <ContentTemplate> <asp:GridView ID="ProductsGridView" runat="server" AllowPaging="True" AutoGenerateColumns="False" BackColor="White" BorderColor="#E7E7FF" BorderStyle="None" BorderWidth="1px" CellPadding="3" DataKeyNames="ProductID" DataSourceID="ProductsDataSource" GridLines="Horizontal"> <FooterStyle BackColor="#B5C7DE" ForeColor="#4A3C8C" /> <Columns> <asp:BoundField DataField="Name" HeaderText="Name" SortExpression="Name" > <ItemStyle Width="240px" /> </asp:BoundField> </Columns> <RowStyle BackColor="#E7E7FF" ForeColor="#4A3C8C" /> <SelectedRowStyle BackColor="#738A9C" Font-Bold="True" ForeColor="#F7F7F7" /> <PagerStyle BackColor="#E7E7FF" ForeColor="#4A3C8C" HorizontalAlign="Right" /> <HeaderStyle BackColor="#4A3C8C" Font-Bold="True" ForeColor="#F7F7F7" /> <AlternatingRowStyle BackColor="#F7F7F7" /> </asp:GridView> <asp:SqlDataSource ID="ProductsDataSource" runat="server" ConnectionString="<%$ ConnectionStrings:AdventureWorksConnectionString %>" SelectCommand="SELECT ProductID, Name, ProductSubcategoryID FROM Production.Product WHERE (ProductSubcategoryID = @SubcategoryID) ORDER BY Name"> <SelectParameters> <asp:Parameter DefaultValue="0" Name="SubcategoryID" /> </SelectParameters> </asp:SqlDataSource> </ContentTemplate> </asp:UpdatePanel> </td> </tr> </table> </div> </form> </body> </html>
Controls that trigger an UpdatePanel control refresh must be registered with the ScriptManager control on the page. This occurs automatically for the child controls in an UpdatePanel control. You can specify triggers declaratively using the Triggers collection of an UpdatePanel control. Additionally, you can programmatically identify triggers and use server code to cause an UpdatePanel control to refresh.
In cases where a trigger control is not available at design time, you can register the control as a trigger by using the RegisterAsyncPostBackControl method of the ScriptManager control. Controls that are programmatically identified as triggers must be registered every time that a postback occurs. We recommend that you put calls to the RegisterAsyncPostBackControl method in the Page_Load event for your page, as shown in the following example:
To programmatically refresh the UpdatePanel control, you can call the Update method of an UpdatePanel control. This is useful if you must perform some processing on the server before refreshing the UpdatePanel control. The following example shows how to refresh an UpdatePanel programmatically.
Protected Sub ChoicesRadioButtonList_SelectedIndexChanged(sender As Object, e As EventArgs) Dim answers As SortedList = Me.AnsweredQuestions Dim r As RadioButtonList = CType(sender, RadioButtonList) answers(r.ToolTip) = r.SelectedValue Me.AnsweredQuestions = answers ResultsList.DataSource = Me.AnsweredQuestions ResultsList.DataBind() If Me.AnsweredQuestions.Count = SurveyDataList.Items.Count Then _ SubmitButton.Visible = True UpdatePanel1.Update() End Sub
The following example shows a page that registers a control as a trigger by using the RegisterAsyncPostBackControl method. It then programmatically refreshes an UpdatePanel control by using the Update method.
<%@ Page Language="VB" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server"> Protected Property AnsweredQuestions As SortedList Get If ViewState("AnsweredQuestions") IsNot Nothing Then Return CType(ViewState("AnsweredQuestions"), SortedList) Else Return New SortedList() End If End Get Set ViewState("AnsweredQuestions") = value End Set End Property Protected Sub Page_Load() ScriptManager1.RegisterAsyncPostBackControl(SurveyDataList) End Sub Protected Sub ChoicesRadioButtonList_SelectedIndexChanged(sender As Object, e As EventArgs) Dim answers As SortedList = Me.AnsweredQuestions Dim r As RadioButtonList = CType(sender, RadioButtonList) answers(r.ToolTip) = r.SelectedValue Me.AnsweredQuestions = answers ResultsList.DataSource = Me.AnsweredQuestions ResultsList.DataBind() If Me.AnsweredQuestions.Count = SurveyDataList.Items.Count Then _ SubmitButton.Visible = True UpdatePanel1.Update() End Sub Protected Sub SubmitButton_Click(sender As Object, e As EventArgs) ' Submit responses. End Sub </script> <html xmlns="http://www.w3.org/1999/xhtml"> <head id="Head1" runat="server"> <title>Registering Controls as Async Postback Controls</title> <style type="text/css"> .AnswerFloatPanelStyle { background-color: bisque; position: absolute; right: 10px; height: 130px; width: 150px; border-right: silver thin solid; border-top: silver thin solid; border-left: silver thin solid; border-bottom: silver thin solid; } </style> </head> <body> <form id="form1" runat="server"> <div> <asp:ScriptManager ID="ScriptManager1" runat="server" /> <div id="AnswerFloatPanel" class="AnswerFloatPanelStyle" runat="server"> <asp:UpdatePanel ID="UpdatePanel1" UpdateMode="Conditional" runat="server"> <ContentTemplate> Completed Questions: <asp:DataList ID="ResultsList" runat="server"> <ItemTemplate> <asp:Label ID="ResultQuestion" runat="server" Text='<%# Eval("Key") %>' /> :: <asp:Label ID="ResultAnswer" runat="server" Text='<%# Eval("Value") %>' /> </ItemTemplate> </asp:DataList> <p style="text-align: right"> <asp:Button ID="SubmitButton" Text="Submit" runat="server" Visible="false" OnClick="SubmitButton_Click" /> </p> <asp:Label ID="Message" runat="Server" /> </ContentTemplate> </asp:UpdatePanel> </div> <asp:XmlDataSource ID="SurveyDataSource" runat="server" XPath="/Questions/Question" DataFile="~/App_Data/SurveyQuestions.xml"/> <asp:DataList ID="SurveyDataList" DataSourceID="SurveyDataSource" runat="server"> <ItemTemplate> <table cellpadding="2" cellspacing="2"> <tr> <td valign="top"> <asp:Label id="QuestionLabel" Text='<%# XPath("@Title")%>' runat="server" /> </td> </tr> <tr><td> <asp:RadioButtonList ID="ChoicesRadioButtonList" runat="server" DataSource='<%#XPathSelect("Choices/Choice") %>' DataTextField="InnerText" DataValueField="InnerText" AutoPostBack="True" ToolTip='<%# "Question" + XPath("@ID") %>' OnSelectedIndexChanged="ChoicesRadioButtonList_SelectedIndexChanged"/> </td></tr> </table> <hr /> </ItemTemplate> </asp:DataList> </div> </form> </body> </html>
You can add an UpdatePanel to a user control or to a custom control. However, the page that contains your control might not include the necessary ScriptManager control with its EnablePartialRendering property set to true. Therefore, in your custom control you can determine whether partial-page rendering is enabled by calling the static GetCurrent method of the ScriptManager control. If there is no ScriptManager control on the page, the GetCurrent method returns null. Otherwise, you can check the value of the EnablePartialRendering property of the ScriptManager control and include an UpdatePanel control if the EnablePartialRendering property returns true.
The following example shows the CreateChildControls method of a custom control that inherits from the CompositeControl class. If partial-page rendering is enabled for the page, the custom control puts its contents in an UpdatePanel control.
Protected Overrides Sub CreateChildControls() MyBase.CreateChildControls() Dim parent As Control Dim container As Control ' Get a reference to the ScriptManager object for the page ' if one exists. Dim sm As ScriptManager = ScriptManager.GetCurrent(Page) If sm Is Nothing OrElse Not sm.EnablePartialRendering Then ' If partial rendering is not enabled, set the parent ' and container as a basic control. container = New Control() parent = container Else ' If partial rendering is enabled, set the parent as ' a new UpdatePanel object and the container to the ' content template of the UpdatePanel object. Dim up As UpdatePanel = New UpdatePanel() container = up.ContentTemplateContainer parent = up End If AddDataboundControls(container) Controls.Add(parent) End Sub
The following example shows a custom control that includes an UpdatePanel control if partial-page rendering is enabled.
<%@ Page Language="VB" AutoEventWireup="true" %> <%@ Register Namespace="UpdatePanelTutorialCustom.VB" TagPrefix="sample" %> <!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 id="Head1" runat="server"> <title>Browse Products</title> <script runat="server"> Protected Sub ProductsView1_RowCommand(ByVal sender As Object, ByVal e As EventArgs) ShoppingCartList.DataSource = ProductsView1.Cart ShoppingCartList.DataBind() End Sub </script> </head> <body> <form id="form1" runat="server"> <div> <asp:ScriptManager runat="server" ID="ScriptManager1" EnablePartialRendering="false" /> <h2>Browse Products</h2> <sample:ProductsView runat="server" ID="ProductsView1" PageSize="5" OnRowCommand="ProductsView1_RowCommand" /> <asp:UpdatePanel runat="server" ID="CartUpdatePanel"> <ContentTemplate> <h3>Selected Items</h3> <asp:BulletedList BulletStyle="numbered" runat="server" ID="ShoppingCartList" /> </ContentTemplate> </asp:UpdatePanel> </div> </form> </body> </html>
Imports System Imports System.Data Imports System.Configuration Imports System.Collections Imports System.Web Imports System.Web.Security Imports System.Web.UI.WebControls Imports System.Web.UI.WebControls.WebParts Imports System.Web.UI.HtmlControls Imports System.Web.UI Imports System.Drawing Namespace UpdatePanelTutorialCustom.VB Public Class ProductsView Inherits CompositeControl Private _pageSize As Integer Private _cart As ArrayList Private Shared ReadOnly EventRowCommand As Object = New Object() Public Property PageSize() As Integer Get Return _pageSize End Get Set(ByVal value As Integer) _pageSize = value End Set End Property Public ReadOnly Property Cart() As ArrayList Get Return _cart End Get End Property Protected Overrides Sub CreateChildControls() MyBase.CreateChildControls() Dim parent As Control Dim container As Control ' Get a reference to the ScriptManager object for the page ' if one exists. Dim sm As ScriptManager = ScriptManager.GetCurrent(Page) If sm Is Nothing OrElse Not sm.EnablePartialRendering Then ' If partial rendering is not enabled, set the parent ' and container as a basic control. container = New Control() parent = container Else ' If partial rendering is enabled, set the parent as ' a new UpdatePanel object and the container to the ' content template of the UpdatePanel object. Dim up As UpdatePanel = New UpdatePanel() container = up.ContentTemplateContainer parent = up End If AddDataboundControls(container) Controls.Add(parent) End Sub Private Sub GridView_RowCommand(ByVal sender As Object, ByVal e As GridViewCommandEventArgs) Dim productID As String If e.CommandName = "AddToCart" Then productID = CType(sender, GridView).DataKeys(Convert.ToInt32(e.CommandArgument)).Value.ToString() If _cart Is Nothing Then GetCart() If _cart.IndexOf(productID) = -1 Then _ _cart.Add(productID) ViewState("Cart") = _cart End If If e.CommandName = "RemoveFromCart" Then productID = CType(sender, GridView).DataKeys(Convert.ToInt32(e.CommandArgument)).Value.ToString() If _cart Is Nothing Then GetCart() _cart.Remove(productID) ViewState("Cart") = _cart End If Me.OnRowCommand(New EventArgs()) End Sub Private Sub GetCart() If ViewState("Cart") Is Nothing Then _cart = New ArrayList() Else _cart = CType(ViewState("Cart"), ArrayList) End If End Sub Custom Event RowCommand As EventHandler RaiseEvent(ByVal sender As Object, ByVal e As EventArgs) End RaiseEvent AddHandler(ByVal value As EventHandler) Events.AddHandler(EventRowCommand, value) End AddHandler RemoveHandler(ByVal value As EventHandler) Events.RemoveHandler(EventRowCommand, value) End RemoveHandler End Event Protected Overridable Sub OnRowCommand(ByVal e As EventArgs) Dim handler As EventHandler = CType(Events(EventRowCommand), EventHandler) If handler IsNot Nothing Then handler(Me, e) End If End Sub Private Sub AddDataboundControls(ByVal parent As Control) Dim ds As SqlDataSource = New SqlDataSource() ds.ID = "ProductsSqlDataSource" ds.ConnectionString = _ ConfigurationManager.ConnectionStrings("AdventureWorksConnectionString").ConnectionString ds.SelectCommand = _ "SELECT Production.ProductDescription.Description, Production.Product.Name, Production.ProductPhoto.ThumbnailPhotoFileName, " & _ "Production.Product.ProductID " & _ "FROM Production.Product INNER JOIN " & _ "Production.ProductProductPhoto ON Production.Product.ProductID = Production.ProductProductPhoto.ProductID INNER JOIN " & _ "Production.ProductPhoto ON Production.ProductProductPhoto.ProductPhotoID = Production.ProductPhoto.ProductPhotoID INNER JOIN " & _ "Production.ProductModelProductDescriptionCulture ON " & _ "Production.Product.ProductModelID = Production.ProductModelProductDescriptionCulture.ProductModelID INNER JOIN " & _ "Production.ProductDescription ON " & _ "Production.ProductModelProductDescriptionCulture.ProductDescriptionID = Production.ProductDescription.ProductDescriptionID" Dim gv As GridView = New GridView() gv.ID = "ProductsGridView" gv.DataSourceID = ds.ID gv.AutoGenerateColumns = False gv.DataKeyNames = New String() {"ProductID"} gv.GridLines = GridLines.None gv.HeaderStyle.BackColor = Color.LightGray gv.AlternatingRowStyle.BackColor = Color.LightBlue gv.AllowPaging = True gv.PageSize = _pageSize AddHandler gv.RowCommand, AddressOf Me.GridView_RowCommand Dim if1 As ImageField = New ImageField() if1.HeaderText = "Product" if1.DataImageUrlField = "ThumbnailPhotoFileName" if1.DataImageUrlFormatString = "..\images\thumbnails\{0}" Dim bf1 As BoundField = New BoundField() bf1.HeaderText = "Name" bf1.DataField = "Name" Dim bf2 As BoundField = New BoundField() bf2.HeaderText = "Description" bf2.DataField = "Description" Dim btf1 As ButtonField = New ButtonField() btf1.Text = "Add" btf1.CommandName = "AddToCart" Dim btf2 As ButtonField = New ButtonField() btf2.Text = "Remove" btf2.CommandName = "RemoveFromCart" gv.Columns.Add(if1) gv.Columns.Add(bf1) gv.Columns.Add(bf2) gv.Columns.Add(btf1) gv.Columns.Add(btf2) parent.Controls.Add(New LiteralControl("<br />")) parent.Controls.Add(gv) parent.Controls.Add(New LiteralControl("<br />")) parent.Controls.Add(ds) End Sub End Class End Namespace