I was working on a project where I needed to use a repeater to list some records. Repeater is the most flexible tool when advanced UI and record editing options are needed. In order to provide rich user experience I decided to use Microsoft ASP.NET AJAX Extension library, actually meaning UpdatePanel. My main purpose is to provide an UpdatePanel for each record in Repeater. The user will be able to edit any record listed in Repeater but only edited records information will be refreshed in its own UpdatePanel. Additionally Repeater control will be in an extra UpdatePanel in order to populate Repeater without full page refresh.
In summary;
First of all let’s see our markup code:
<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional"> <ContentTemplate> <asp:Repeater ID="Repeater1" runat="server"> <ItemTemplate> <asp:UpdatePanel UpdateMode="Conditional" ID="UpdatePanel2" runat="server"> <ContentTemplate> <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox> <asp:Label ID="Label1" runat="server" Text="Label"></asp:Label> <asp:Button ID="Button2" runat="server" Text="Button" /> </ContentTemplate> </asp:UpdatePanel> </ItemTemplate> </asp:Repeater> <asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_Click" /> </ContentTemplate> </asp:UpdatePanel>
We will need some dummy data to populate our Repeater control. The code below is just creating a table with dummy data and binding it to Repeater.
Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Dim mytable As New Data.DataTable Dim mycolumn As New Data.DataColumn("MyData") mytable.Columns.Add(mycolumn) Dim myrow As Data.DataRow myrow = mytable.NewRow myrow.Item(0) = "Trial Row 1" mytable.Rows.Add(myrow) myrow = mytable.NewRow myrow.Item(0) = "Trial Row 2" mytable.Rows.Add(myrow) myrow = mytable.NewRow myrow.Item(0) = "Trial Row 3" mytable.Rows.Add(myrow) Repeater1.DataSource = mytable Repeater1.DataBind() End Sub
It’s time to set up bindings for our Repeater control. Actually there is nothing special here; we are just accessing our UpdatePanel control from inside our Repeater in order to be able to access other controls which are inside UpdatePanels ContentTemplate. Finally we bind data to controls.
Protected Sub Repeater1_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.RepeaterItemEventArgs) Handles Repeater1.ItemDataBound If e.Item.ItemType = ListItemType.Item Or e.Item.ItemType = ListItemType.AlternatingItem Then Dim CurrentUpdatePanel As System.Web.UI.UpdatePanel = e.Item.FindControl("UpdatePanel2") Dim mylabel As System.Web.UI.WebControls.Label = CurrentUpdatePanel.FindControl("Label1") Dim mybutton As System.Web.UI.WebControls.Button = CurrentUpdatePanel.FindControl("Button2") mylabel.Text = e.Item.DataItem.item(0) mybutton.Text = "Update" End If End Sub
Here comes the tricky part. How we will handle button clicks? Remember, we have a ScriptManager on each AJAX based web page. The role of ScriptManager is to handle all requests etc. Hopefully our populated UpdatePanels should be handled by our ScriptManager as well. That’s why we are using ScriptManagers PreRender event. All AJAX based renders on our page will fire this event. But we don’t need to handle all renders. We just need the ones coming from our populated UpdatePanels inside Repeater1. In order to get the sender of PreRendering we use AsyncPostBackSourceElementID property of ScriptManager. The source controls rendered ID will contain our Repeaters and Buttons IDs. Additionally it will contain the row number of repeated ItemTemplate inside Repeater. That will be something like Repeater1$ctl01$Button2. After getting the row number from incoming ID we can access all data inside our Repeater. We can save, edit anything to database and let our ScriptManager render UpdatePanel with new values. In our example we are getting the value inside TextBox and transferring it to a Label.
Protected Sub AnyClick(ByVal sender As Object, ByVal e As System.EventArgs) Handles ScriptManager1.PreRender Dim IncID As String = CType(sender, System.Web.UI.ScriptManager).AsyncPostBackSourceElementID.ToString Dim RowIndex As Integer = 0 If IncID.IndexOf(Repeater1.ID) <> -1 And IncID.IndexOf("Button2") <> -1 Then IncID = IncID.Replace(Repeater1.ID & "$ctl", "") IncID = IncID.Replace("$Button2", "") RowIndex = CInt(IncID) Dim mytextbox As System.Web.UI.WebControls.TextBox = Repeater1.Items(RowIndex).FindControl("Textbox1") Dim mylabel As System.Web.UI.WebControls.Label = Repeater1.Items(RowIndex).FindControl("label1") mylabel.Text = mytextbox.Text End If End Sub
Now you have got a web page that never gets fully refreshed. You can populate the repeater without full page refresh and edit, save all records without even full repeater refresh. Finally I would like to remind you to not forget to set UpdateMode properties of UpdatePanels to "Conditional".
Have fun :)