Binding To An IEnumerable<valueType>

by DanM 26. January 2010 14:30

Didn’t find this in any easily searchable place, so here’s one for reference. Consider a scenario where you’re binding a templated control to an IEnumerable<string> object. In my case, I needed to display a list of the keys in my cache.

protected void Page_Load(object sender, EventArgs e)
{
   if (!IsPostBack)
   {
      lvwKeys.DataSource = AllCacheKeys();
      lvwKeys.DataBind();
   }
}

private IEnumerable<string> AllCacheKeys()
{
   IDictionaryEnumerator enumerator = HttpContext.Current.Cache.GetEnumerator();
   while (enumerator.MoveNext())
   {
      yield return enumerator.Key.ToString();
   }
}

So how do I reference the string values in my template? <%#Eval(“xyz”) %> expects xyz to be the property of the object being bound to, but a simple string has no property for its value. I’ve seen <%#Eval(“.”) %> suggested else place where . is supposed to refer to the object as whole, but this does not work here. Instead, we must use <%# Container.DataItem %> to refer to the object itself.

<asp:ListView runat="server" ID="lvwKeys">
   <LayoutTemplate>
      <table class="form">
         <tbody>
            <asp:PlaceHolder ID="itemPlaceholder" runat="server" />
         </tbody>
      </table>
   </LayoutTemplate>
   <ItemTemplate>
      <tr>
         <td><%# Container.DataItem %></td>
      </tr>
   </ItemTemplate>
</asp:ListView>

Indeed, this the way to approach binding IEnumerable<T> where T is any value type – int, double, bool, etc. Container.DataItem returns the string representation of the value you are binding to. In the case of bool, it renders True and False.

Hope that helps. Happy coding!

Comments (2) -

James Hart
James Hart United Kingdom
1/26/2010 4:49:22 PM #

Well, strictly speaking, Container.DataItem returns the Current value of the enumerator as an Object (boxed if necessary); wrapping it in <%# %> just calls ToString() on it at databinding time.

You can cast Container.DataItem to a type if you want to call methods on it:

<%# ((string) Container.DataItem).ToUpperInvariant() %>

for example. That's more useful if you're dealing with rich objects.

Of course, if the webforms team had embraced generics back in 2005 or so we might also have got a generic ListView<T> control with a strongly typed Container.DataItem, and we could finally have ditched that ugly Bind() method...

Dan
Dan United Kingdom
1/26/2010 10:13:55 PM #

Ah. That clears it up a bit more. Thanks. I still don't know where the #Eval(".") notation came from though. It's not the easiest thing to Google either.

I think some alt.net peeps would say that ListView<T> is just another View<T> in MVC...

Comments are closed