April 1020

Conditional logic in an ASP.NET Repeater

The premise for this is quite straightforward, I’m using an ASP.NET Repeater control to display the results of a query – one row per item. As an example I’m going to display a list of students and a Checkbox IFF the data allows. To do that I need to create a function in the code behind and then pass my arguments to it from within my repeater.

Unfortunately Repeater controls do not allow you to embed <% if … %> statements, otherwise I could do something like this:

<ItemTemplate>
    <tr>
        <td class="contactNoCol"><%#Eval("ContactNo")%></td>
        <td><%#Eval("FullName")%></td>
        <% If String.IsNullOrEmpty(Eval("SelectText")) Then%>
        <td class="chkColumn"><%#Eval("SelectText")%></td>
        <% Else%>
        <td class="chkColumn"><asp:CheckBox ID="chk" runat="server" /></td>
        <% End If %>
    </tr>
</ItemTemplate>

Using this approach will result in an error: “Databinding methods such as Eval(), XPath(), and Bind() can only be used in the context of a databound control.” Annoyingly it isn’t valid to use this kind of logic in the repeater, despite the fact that Visual Studio helped me write it by providing me with intellisense.

To get around that I moved the logic to a function in the code behind. This has a few advantages, the logic can be a lot more complicated and it keeps the aspx file a bit cleaner / free from the logic. This is how I’m doing it now:

<ItemTemplate>                    
    <tr>
        <td class="contactNoCol"><%#Eval("ContactNo")%></td>
        <td><%#Eval("FullName")%></td>
        <td class="chkColumn">
            <asp:CheckBox ID="chk" runat="server" Visible='<%# ShouldShowIf(False, Eval("SelectText")) %>' />
            <asp:Literal ID="ltSelectText" runat="server" Text='<%#Eval("SelectText")%>' 
                Visible='<%# ShouldShowIf(True, Eval("SelectText")) %>' /></td>
    </tr>
</ItemTemplate>

The function ShouldShowIf is declared in the code behind for this page:

Public Shared Function ShouldShowIf(ByVal returnBool As Boolean, ByVal value As String) As String
    Return If(value.Length > 0, returnBool, Not returnBool)
End Function

ShouldShowIf takes 2 arguments, the value to evaluate and the flavour of the Boolean to return. I needed to allow the calling code to determine whether it should return True or False because the checkbox should be shown if the SelectText is empty otherwise it should display the SelectText value.

I’ve used this approach before, but forgot about it – so I’m posting it up in the hopes that it helps someone else, if nothing else it will serve to remind me how to do this in future.

Permalink | Comments (5)

Comments

  1. Alex United Kingdom Alex (Wednesday, April 21, 2010) #

    Is there a reason why you didnt consider the Repeater.ItemDataBound event (msdn.microsoft.com/.../...ater.itemdatabound.aspx)
    Allows you to cleanly handle such situations from the server side when the control is being bound with you data. Just a thought.

  2. Alex United Kingdom Alex (Wednesday, April 21, 2010) #

    FYI, looks like there is a slight bug in  BlogEngine.NET 1.6.0.0 in the way that it deals identifying links in comments and wrapping them  in anchor tags. The previous link is broken and ends before the last ")".

  3. SimonMartin United Kingdom SimonMartin (Saturday, April 24, 2010) #

    Hi Alex,

    I wanted to try to keep as much of the presentation in the mark-up as I could; the if statement indicating to the designer that there was either a checkbox or some text. Whereas if I'd added a checkbox or literal in the ItemDataBound event that would be less obvious, anyone needing to change the behaviour would need to hunt a bit more to find where and how to make their change - and also would need to know VB.

    But also I'd run into problems with the ItemDataBound on this page and was looking for a 'quick' solution. The code shown is from a 3rd level repeater (yup a repeater in a repeater in a repeater), not pretty!

    To give a bit of background to the problem, I had a list<Student> which was ordered by AcademicYear, TeachingSet, LastName, Forenames and this had to be displayed as shown in this www.ifslearning.ac.uk/files/student-table.jpg image, grouped by AcademicYear which contained 0 or more TeachingSets which contained 1 or more Students. To get the list bound to a table was easy, but to achieve the grouping I initially wanted to use the ItemDataBound to check the AcademicYear of the previous student and create a header row but it was getting really messy and I couldn't inject a row for the 1st item - so gave in to time constraints and ended up with the above.

    Judging from the size of this reply I think another post is in order to more fully explain things!

  4. SimonMartin United Kingdom SimonMartin (Saturday, April 24, 2010) #

    Thanks for the tip on the link issue, I'll look into that and try to get it fixed Smile

  5. Alex United Kingdom Alex (Sunday, April 25, 2010) #

    Maybe it would be best to look into implementing a Model View Presenter architecture (time permitting) then you could look into some sort of View Model that your designers can work with. Taking away the tight coupling between the layers (views / server code) and removing the room for error. Just a thought. http://webformsmvp.com/

Comments are closed