Variation: Alternating Data Types
Suppose I wanted to expand the example further to support binding a list of different types of classes (say, Animal and Human). The binding code would get very complicated, as the bound contents inside of placeholders still get evaluated even when the placeholders are not visible.
To simplify the binding code, you can use a repeater to wrap the objects of different types (pay particular attention to the use of the ListWrap function):
<%@ Page Language="C#" AutoEventWireup="true" %>
<script runat="server">
public class Animal
{
public Boolean CanFly { get; set; }
public String Description { get; set; }
}
public class Human
{
public String Name { get; set; }
public String Description { get; set; }
}
protected void Page_Load(Object sender, System.EventArgs e)
{
rpItems.DataSource = new List<Object> {
new Animal {CanFly = false, Description = "Duck"},
new Animal {CanFly = true, Description = "Duck"},
new Animal {CanFly = false, Description = "Duck"},
new Animal {CanFly = true, Description = "Goose!"},
new Human {Name = "Elephant Man", Description = "I am not an animal!"}};
rpItems.DataBind();
}
protected List<Object> ListWrap<SomeType>(Object item)
{
List<Object> returnList = new List<object>();
if (item is SomeType)
{
returnList.Add(item);
}
return returnList;
}
</script>
<html>
<head>
<title>Markup Conditions Using Bound Code Block</title>
</head>
<body>
<form id="frmMain" runat="server">
<asp:Repeater runat="server" ID="rpItems">
<HeaderTemplate>
<ul>
</HeaderTemplate>
<ItemTemplate>
<li>
<%----%>
<asp:Repeater runat="server" DataSource="<%# ListWrap<Animal>(Container.DataItem)%>">
<ItemTemplate>
<asp:PlaceHolder runat="server" Visible="<%# (Container.DataItem as Animal).CanFly%>">
<b>I can fly!</b>
</asp:PlaceHolder>
<asp:PlaceHolder runat="server" Visible="<%# !(Container.DataItem as Animal).CanFly %>">
I can't fly.
</asp:PlaceHolder>
<%# HttpUtility.HtmlEncode(((Animal)Container.DataItem).Description) %>
</ItemTemplate>
</asp:Repeater>
<%-- This repeater is bound to a list with one or zero humans. --%>
<asp:Repeater runat="server" DataSource="<%# ListWrap<Human>(Container.DataItem)%>">
<ItemTemplate>
<%# HttpUtility.HtmlEncode((Container.DataItem as Human).Name)%>:
"<%# HttpUtility.HtmlEncode((Container.DataItem as Human).Description)%>"
</ItemTemplate>
</asp:Repeater>
</li>
</ItemTemplate>
<FooterTemplate>
</ul>
</FooterTemplate>
</asp:Repeater>
</form>
</body>
</html>
<%@ Page Language="vb" AutoEventWireup="false" %>
<script runat="server">
Public Class Animal
Public Property CanFly As Boolean
Public Property Description As String
End Class
Public Class Human
Public Property Name As String
Public Property Description As String
End Class
Protected Sub Page_Load(sender As Object, e As System.EventArgs) Handles Me.Load
rpItems.DataSource = New List(Of Object) From {
New Animal With {.CanFly = False, .Description = "Duck"},
New Animal With {.CanFly = True, .Description = "Duck"},
New Animal With {.CanFly = False, .Description = "Duck"},
New Animal With {.CanFly = True, .Description = "Goose!"},
New Human With {.Name = "Elephant Man", .Description = "I am not an animal!"}}
rpItems.DataBind()
End Sub
Protected Function ListWrap(Of SomeType)(ByVal item As Object) As List(Of Object)
Dim returnList As New List(Of Object)()
If TypeOf item Is SomeType Then
returnList.Add(item)
End If
Return returnList
End Function
</script>
<html>
<head>
<title>Markup Conditions Using Bound Code Block</title>
</head>
<body>
<form id="frmMain" runat="server">
<asp:Repeater runat="server" ID="rpItems">
<HeaderTemplate>
<ul>
</HeaderTemplate>
<ItemTemplate>
<li>
<%----%>
<asp:Repeater runat="server"
DataSource="<%# ListWrap(Of Animal)(Container.DataItem)%>">
<ItemTemplate>
<asp:PlaceHolder runat="server" Visible="<%# DirectCast(Container.DataItem, Animal).CanFly%>">
<b>I can fly!</b>
</asp:PlaceHolder>
<asp:PlaceHolder runat="server" Visible="<%# Not DirectCast(Container.DataItem, Animal).CanFly %>">
I can't fly.
</asp:PlaceHolder>
<%# HttpUtility.HtmlEncode(DirectCast(Container.DataItem, Animal).Description) %>
</ItemTemplate>
</asp:Repeater>
<%----%>
<asp:Repeater runat="server"
DataSource="<%# ListWrap(Of Human)(Container.DataItem)%>">
<ItemTemplate>
<%# HttpUtility.HtmlEncode(DirectCast(Container.DataItem, Human).Name)%>:
"<%# HttpUtility.HtmlEncode(DirectCast(Container.DataItem, Human).Description)%>"
</ItemTemplate>
</asp:Repeater>
</li>
</ItemTemplate>
<FooterTemplate>
</ul>
</FooterTemplate>
</asp:Repeater>
</form>
</body>
</html>
When the item is of the incorrect type, the repeater gets bound to an empty list, and the binding code inside of a repeater bound to an empty collection does not get evaluated.