The following is an extremely simplified version of what I
did to solve the problem; however, the techniques used are the same.
So, let us dive in and start by creating the project. I am
using an ASP.Net AJAX-Enabled Web Site, I will call it EventHandlingInRepeaterControl.
Figure 1
Style sheets are very important for this example, so here is
the code that I am using for the style sheet.
Listing 1: Stylesheet.css
.FlagHeader
{
width:50px;
text-align:center;
}
.NameHeader
{
width:100px;
}
.RedButton
{
width:50px;
background-color: Red;
}
.YellowButton
{
width:50px;
background-color:Yellow;
}
.GreenButton
{
width:50px;
background-color:Green;
}
I added a repeater control, tucked safely within an Update
Panel, to Default.aspx.
Listing 2: Default.aspx
<asp:UpdatePanel ID="upExample" runat="server">
<ContentTemplate>
<asp:Repeater ID="drExample" runat="server"
OnItemCommand=" drExample_ItemCommand ">
<HeaderTemplate>
<div>
<asp:Label ID="lblName" runat="server" Text="Name"
Width="100px" CssClass="NameHeader" />
<asp:Label ID="lFlag1" runat="server" Text="Flag 1"
Width="50px" CssClass="FlagHeader" />
<asp:Label ID="lFlag2" runat="server" Text="Flag 2"
Width="50px" CssClass="FlagHeader" />
<asp:Label ID="lFlag3" runat="server" Text="Flag 3"
Width="50px" CssClass="FlagHeader" />
</div>
</HeaderTemplate>
<ItemTemplate>
<div>
<asp:Label ID="lName" runat="server" Width="100px"
CssClass="NameDetail"
Text='<%# Eval("ItemName") %>' />
<asp:Button ID="bFlag1" runat="server" Width="50px"
CssClass="RedButton" />
<asp:Button ID="bFlag2" runat="server" Width="50px"
CssClass="RedButton" />
<asp:Button ID="bFlag3" runat="server" Width="50px"
CssClass="RedButton" />
</div>
</ItemTemplate>
</asp:Repeater>
</ContentTemplate>
</asp:UpdatePanel>
Notice that this is an extremely basic and simple setup. I
highlighted the two most important parts of the repeater.
1.
ItemName is the name of the column of the dataset that I will be passing
to the repeater.
2.
drExample_ItemCommand is the function that will be used to parse which
button is being clicked.
Okay, now that the basics of the form are setup, we need to
load the repeater when the page loads. For this example I did not want to do
any data interaction with an actual database, so I created an array, and placed
the data from the array into a dataset for binding. Here are the two functions
used for doing this:
Listing 3: Default.aspx.vb
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)
Handles Me.Load
If IsPostBack = False Then
drExample.DataSource = getData()
drExample.DataBind()
End If
End Sub
Private Function getData() As DataSet
Dim arExample() As String = {"Test 1", "Test 2", "Test 3", "Test 4"}
Dim ds As New DataSet
Dim dt As New DataTable("ExampleTable")
ds.Tables.Add(dt)
Dim dc As New DataColumn("ItemName")
dt.Columns.Add(dc)
Dim cnt As Int32 = 0
For cnt = 0 To arExample.GetUpperBound(0) - 1
Dim dr As DataRow = dt.NewRow
dr("ItemName") = arExample(cnt).ToString
dt.Rows.Add(dr)
Next
Return ds
End Function
However, this would be good enough to make the page display
the repeater, but not enough to really make the repeater functional like I
needed. After all, without knowing the exact name of the button that was being
pushed, and even at that, not knowing what row that button belonged to, well,
there had to be a way of doing this, and there is. I used ItemDataBound to
change some of the properties on the buttons at run-time. Here is the
function:
Listing 4: Default.aspx.vb
Protected Sub drExample_ItemDataBound(ByVal sender As Object, ByVal e As
System.Web.UI.WebControls.RepeaterItemEventArgs) Handles
drExample.ItemDataBound
If e.Item.ItemType = ListItemType.Item Or e.Item.ItemType =
ListItemType.AlternatingItem Then
Dim bFlag1 As Button = CType(e.Item.FindControl("bFlag1"), Button)
Dim bFlag2 As Button = CType(e.Item.FindControl("bFlag2"), Button)
Dim bFlag3 As Button = CType(e.Item.FindControl("bFlag3"), Button)
Dim sArgument As String = CType(e.Item.DataItem,
DataRowView).Row.Item("ItemName").ToString
If Not IsNothing(bFlag1) Then
setFlagCommands(bFlag1, "Flag1_Change", sArgument)
End If
If Not IsNothing(bFlag2) Then
setFlagCommands(bFlag2, "Flag2_Change", sArgument)
End If
If Not IsNothing(bFlag3) Then
setFlagCommands(bFlag3, "Flag3_Change", sArgument)
End If
End If
End Sub
Private Sub setFlagCommands(ByVal bFlag As Button, ByVal sCommand As String,
ByVal sArgument As String)
bFlag.CommandName = sCommand
bFlag.CommandArgument = sArgument
End Sub
To explain this code:
I first check to make sure that I am looking in the Item or
the Alternating Item regions of the repeater control. The buttons that I want
to manipulate are there, so why waste cycles...
Then I take the three buttons on each row of the repeater
and cast them into an actual button variable. This is for simplicity in the
rest of the function.
Then I create the Command Argument that will be set on the
button. I am not using it here in the example, but in the real world I set
this to the Record Identifier, so I could update the correct record in the
database.
I then check to make sure the buttons are instantiated and
call the subroutine that sets the command name and the command argument.
We do all of that so that when the drExample_ItemCommand is
fired, I can make sure the right code is being called.
Now, when this page is run it looks like this:
Figure 2
Now, I will click on Test 1/Flag 1.
Figure 3
As you can see, the button is now green.
Now, click on Test 2/ Flag 2 once.
Figure 4
Then click a second time.
Figure 5
Then click on Test 3/Flag 3.
Figure 6
Again click a second time.
Figure 7
I changed the behavior on each flag so that there was a
reason to use the command name. I did not have to go through the drExample_ItemDataBound
step here; this is a simple example, but for anything harder where the buttons
need to do vastly different things and they need to save information to a
database, that step is crucial, so I added it here to help in a real world
situation.