Binding to anonymous types in an Xbap or Silverlight application

It's easy to use Linq queries to create objects, and to use {Binding}s to bind properties of those objects into your view. If you're doing this for an application that will run as an Xbap ("WPF Browser Application") or as a Silverlight app, just note that you need to generate nominal types rather than anonymous types.

For example, say you have a bound ListBox like:

<ListBox Name="ListBox1">

    <ListBox.ItemTemplate>

        <DataTemplate>

            <TextBlock Text="{Binding First}" />

        </DataTemplate>

    </ListBox.ItemTemplate>

</ListBox>

... where the ListBox ItemsSource is established with the following code at initialization-time:

public partial class Window1 : Window

{

    private Collection<Person> _collection = new Collection<Person>()

    {

        new Person() { FirstName = "John", LastName = "Doe" },

        new Person() { FirstName = "Jane", LastName = "Doe" },

        new Person() { FirstName = "Fred", LastName = "Flinstone" }

    };

    public Window1()

    {

        InitializeComponent();

        ListBox1.ItemsSource = from person in _collection

                               where person.LastName == "Doe"

                               select new { First = person.FirstName, Last = person.LastName };

    }

}

This won’t show anything in the ListBox. (You might see debug output like “System.Windows.Data Error: 12 : Cannot get 'First' value (type 'String') from '' (type '<>f__AnonymousType0`2')”).

The issue here is that the select statement in the query (select new { First = person.FirstName, Last = person.LastName }) generates an internal (anonymous) type, and with an Xbap or Silverlight app you can’t bind to internal types. The solution is to use a nominal type. E.g., add this class definition:

public class SelectedPerson

{

    public string First { get; set; }

    public string Last { get; set; }

}

... and use it in the select:

ListBox1.ItemsSource = from person in _collection

                       where person.LastName == "Doe"

                       select new SelectedPerson { First = person.FirstName, Last = person.LastName };

... and your list box is populated with “John” and “Jane”.