If you’ve done any amount of web forms development, you certainly couldn’t live without controls like the Repeater or ListView (although some might argue that the ListView control replaces the Repeater control). I had an interesting feature I was developing that ended up with a Repeater control containing a nested user control of sorts.
I had a couple goals in mind. The first was to be able to render some of the bound data straight to the Repeater control, the more typical usage pattern. The second was to be able to pass along some of the bound data to a nested user control within the Repeater. I’ve simplified the concept below:
<asp:Repeater ID="ProfileRepeater" runat="server" OnItemDataBound="ProfileRepeater_ItemDataBound">
<ItemTemplate>
<div>
<%# Eval("Name") %>'s Profile
<CBControls:Profile ID="UserProfile" runat="server" />
</div>
</ItemTemplate>
</asp:Repeater>
With the UI markup clarified above, the databinding was a fairly typical setup leveraging an anonymous type as follows:
protected void Page_Load(object sender, EventArgs e)
{
//Retrieving all profiles from our hypothetical data provider
IEnumerable<Profile> profileData = Profile.GetAll();
//Binding the profiles to our UserProfile control
UserProfile.DataSource = profileData
.Select(data => new {
Name = data.firstName + " " + data.lastName,
Age = data.age,
Location = data.location,
Hometown = data.hometown
});
UserProfile.DataBind();
}
So the idea was to bind, say the “Name” to the Repeater, but I wanted the rest of the data (“Age”, “Location” and “Hometown”) to be consumed by the nested user control. The key to accomplishing this is via the OnItemDataBound event, as specified above in the markup. The implementation for this is as follows:
protected void ProfileRepeater_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
Profile ctrl = e.Item.FindControl("UserProfile") as Profile;
if (ctrl != null)
{
//.NET 3.5 Solution
ctrl.Age = DataBinder.Eval(e.Item.DataItem, "Age");
ctrl.Location = DataBinder.Eval(e.Item.DataItem, "Location");
ctrl.Hometown = DataBinder.Eval(e.Item.DataItem, "Hometown");
//.NET 4.0 Solution using the new "dynamic" keyword to assist with anonymous type passing
dynamic currentProfileData = e.Item.DataItem as dynamic;
ctrl.Age = currentProfileData.Age;
ctrl.Location = currentProfileData.Location;
ctrl.Hometown = currentProfileData.Hometown;
}
}
}
You’ll notice I have provided both the .NET 3.5 and .NET 4.0 solutions for how one would go about this. In my particular case, the project is leveraging .NET 3.5, but if this were .NET 4.0, things could be accomplished slightly more elegantly using the “dynamic” keyword.
Regardless of which framework you’re using, as the method depicts, it is here where we are passing along the data to the nested user control by assigning it to the controls exposed properties. For those of you who prefer to strongly type everything, you’d simply replace the “dynamic” keyword with your own type (the same type that you would project your databinding to in Page_Load) and you’d be good to go!


