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;
-
Repeater will be populated inside UpdatePanel
- Each Repeater Item will contain an independent UpdatePanel.
- Each record in repeater will be edited without full page or full repeater refresh.
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 :)