AspAlliance.com LogoASPAlliance: Articles, reviews, and samples for .NET Developers
URL:
http://aspalliance.com/articleViewer.aspx?aId=1343&pId=-1
Handling Events within a Repeater Control Using ASP.NET 2.0
page
by Shaun Eutsey
Feedback
Average Rating: This article has not yet been rated.
Views (Total / Last 10 Days): 33565/ 38

Introduction

I was confronted a while back with an interesting problem that I was asked to solve. I do say problem; I am not afraid of that word as many people are.  I look at problems as opportunities; opportunities to find solution and to grow, both personally and professionally.

The Problem

I work on site at a fast growing supply chain management company. Many of the people that I am working for started with the company when it was small and they did amazing things to make the company grow with the tools they knew how to use. Now that the company is getting bigger, the old tools (Excel and Access) are being phased out (thankfully!).

One of the things that had been maintained in Excel was a project checklist. This checklist helps the corporate project managers know what needs done and what has been done to keep the business on track. 

I was asked to move this checklist to the application that I had been working on, which is a good move as there have been several versions of the checklist floating around and keeping them synchronized has been difficult at best. The one thing that I was asked to do, above and beyond just collecting and displaying the data that they are using, was to make the interface look as similar as possible to the spreadsheet.

"No problem," I said, until I looked that the spreadsheet and noticed that there was not nice checked boxes with ticks in them, but all of the fields where red, yellow and green. Okay, that is easy enough to re-create in a report, but they wanted the application interface to look the same, so that if they were in a meeting they could click on the red button and make it green or yellow, depending on what button it was. They also wanted the results to be as real time as possible, so if Jane clicked a button, the next time Steve's screen refreshed it would show up. I could not just wait for them to click a save button and batch everything together, I had to save something to the database every time a button was clicked.

As I started thinking about how I was going to address this problem several things occurred to me:

1.      I could not use a series of radio buttons, as it would not fit into the design.

2.      I could use a repeater, but that could prove complicated.

3.      I could go bash my head off of a wall and hope that I cause permanent, irreversible brain damage.

Taking my family into consideration, I did not want my kids growing up with a father who was an invalid, I decided that I would use the repeater and hope the problem was solved before I descended into the depths of insanity.

The Solution

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 ObjectByValAs 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 ObjectByVal 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.

Conclusion

Though at first I thought this was going to be much more daunting than it turned out to be, the discovery process took some time.  If you ever need to do something like this, I do hope that this article will make your life just a little easier and help you produce something that you can brag about. As for me, the resulting page that I put out with this functionality in it is still getting me a lot of praise and I hope that this will help you receive the same. 



©Copyright 1998-2024 ASPAlliance.com  |  Page Processed at 2024-04-24 4:30:30 AM  AspAlliance Recent Articles RSS Feed
About ASPAlliance | Newsgroups | Advertise | Authors | Email Lists | Feedback | Link To Us | Privacy | Search