×

First time here?

You are looking at the most recent posts. You may also want to check out older archives. Please leave a comment, ask a question and consider subscribing to the latest posts via RSS or email. Thank you for visiting!

Just a little post to point out a hidden gem if you are a .NET developer creating a Metro style app: you can bind to anonymous types.  This came up in a discussion with a customer today that I was having and, frankly, I never tried it until then because my mind was back in Silverlight where this isn’t possible.  There may not be a tone of cases where this is valuable for you, but knowing it is there may help.

Let’s assume I have a basic class Person:

   1: public class Person
   2: {
   3:     public int Age { get; set; }
   4:     public string FirstName { get; set; }
   5:     public string Gender { get; set; }
   6: }

And in my application I have a list of that Person type that I somehow received.  In this example, I’m just hard-coding it right now.

   1: List<Person> people = new List<Person>();
   2: people.Add(new Person() { Age = 38, FirstName = "Tim", Gender = "Male" });
   3: people.Add(new Person() { Age = 9, FirstName = "Zoe", Gender = "Female" });
   4: people.Add(new Person() { Age = 5, FirstName = "Zane", Gender = "Male" });

I can then decide I want to bind to a ListView control which has a particular template:

   1: <ListView x:Name="PeopleList" Width="500" Height="300">
   2:     <ListView.ItemTemplate>
   3:         <DataTemplate>
   4:             <StackPanel Orientation="Horizontal">
   5:                 <TextBlock Text="{Binding TheName}" Margin="0,0,10,0" />
   6:                 <TextBlock Text="{Binding GuysAge}" />
   7:             </StackPanel>
   8:         </DataTemplate>
   9:     </ListView.ItemTemplate>
  10: </ListView>

Notice that I’m binding to properties (TheName and GuysAge) that don’t exist on my Person class?  In my code, I can then create a LINQ query to filter out only the “dudes” from my list and bind that result:

   1: var onlyGuys = from g in people
   2:                where g.Gender == "Male"
   3:                orderby g.FirstName descending
   4:                select new
   5:                {
   6:                    GuysAge = g.Age,
   7:                    TheName = g.FirstName,
   8:                    Gender = "Dude"
   9:                };
  10:  
  11: PeopleList.ItemsSource = onlyGuys;

The result is that my ListView now shows 2 people in the list.  Nice.

Get in the real world

Now I would probably agree that since you already have a strongly-typed class this is probably not the use case here.  It certainly might be helpful, but you already have a class (and in this example, one that you completely control so you could shape it to be what you really need).  What about those times you don’t have a class or you don’t own the type coming back?  JSON ring a bell?  Using the sample JSON response (I’m not focusing on how to retrieve data here just how to bind to it) from Twitter APIs, we can demonstrate how this might be more helpful.  Here’s the Twitter JSON data I’m referring to in this example: Twitter Mentions API.

My app wants to retrieve and bind to Twitter data but I don’t really want to have a “TwitterResponse” data type that I have to serialize in/out in my code.  The mention data is an array of mentions.  For the sake of simplicity I’ve basically put my JSON string in a file rather than confuse this sample in how to work with Twitter.  My code looks like this (assume that ‘data’ is the resulting Twitter mentions JSON string:

   1: // parse the data into a JsonArray object
   2: var mentions = JsonArray.Parse(data);
   3:  
   4: // build the query out of the mentions
   5: var qry = from m in mentions
   6:           select new
   7:           {
   8:               MentionText = m.GetObject()["text"].GetString(),
   9:               FromUser = m.GetObject()["user"].GetObject()["screen_name"].GetString(),
  10:               ProfilePic = m.GetObject()["user"].GetObject()["profile_image_url"].GetString()
  11:           };
  12:  
  13: MentionData.ItemsSource = qry;

Notice the LINQ query for creating a “new” type that I will bind to my ListView.  In my XAML I have a simple DataTemplate to demonstrate:

   1: <ListView x:Name="MentionData" Width="500" Height="300">
   2:     <ListView.ItemTemplate>
   3:         <DataTemplate>
   4:             <StackPanel>
   5:                 <TextBlock Text="{Binding FromUser}" />
   6:                 <TextBlock Text="{Binding MentionText}" TextWrapping="Wrap" />
   7:             </StackPanel>
   8:         </DataTemplate>
   9:     </ListView.ItemTemplate>
  10: </ListView>

The result is me being able to create a LINQ query and create a new anonymous type and directly bind to it.

Voila!  Perhaps you already discovered this little gem and are using it.  It is a welcome addition to the data binding story for Metro style app development with XAML and .NET!  Of course the same benefit can be had for XML data using XLINQ queries, so while this example is for JSON data, really any source data applies…it is all about that new anonymous type you create!

Hope this helps!


This work is licensed under a Creative Commons Attribution By license.


4/10/2012 10:01 AM | # re: Metro app development hidden gem: anonymous type binding
When could you not do this? An anonymous type is just a type that is generated by the compiler; it is still a normal type with properties, and XAML binds to properties.
4/10/2012 3:48 PM | # re: Metro app development hidden gem: anonymous type binding
Tim ... Anonymous type binding is awesome ... nice writeup. I stumbled across this recently and was hoping it was going to stick around in the final release. Is that still the plan?
4/10/2012 5:55 PM | # re: Metro app development hidden gem: anonymous type binding
This will be useful to me. (:
4/10/2012 10:02 PM | # re: Metro app development hidden gem: anonymous type binding
@David - you can't do this in Silverlight

@John - yes this should stick...it's a CLR thing, not really a feature of ours :-)
4/11/2012 7:58 AM | # re: Metro app development hidden gem: anonymous type binding
"you can't do this in Silverlight"

What is stopping you? What is it about Silverlight that makes binding to an instance of an anonymous type different from binding to an instance of any other type?
4/11/2012 7:47 PM | # re: Metro app development hidden gem: anonymous type binding
@David - well if you try you'll see it won't work ;-) -- I believe the core differences is that the Core CLR types produced in Silverlight are internal versus how the full .NET framework does them.
4/12/2012 7:29 AM | # re: Metro app development hidden gem: anonymous type binding
One warning to take into consideration, if the developer obfuscates the code the properties names of the anonymous type may change...
5/1/2012 6:05 AM | # re: Metro app development hidden gem: anonymous type binding
A gem indeed, certainly makes it much easier to work with JSON. I've often chosen XML over it out of sheer lazyness - as you said, you need to have a TwitterReponse sort of model class etc
5/11/2012 6:10 AM | # re: Metro app development hidden gem: anonymous type binding
Actually, binding anonymous types has always been possible, even in Silverlight, it's just a matter of placing the appropriate [assembly:InternalsVisibleTo()] attribute so that the DataBinding engine sees the properties generated for anonymous types.

One other thing, one should never Databind directly to a LINQ expression because of its lazy nature, unless it is terminated by a ToArray() or ToList() operator. If not, the DataBinding engine may evaluate the query multiple times, leading to very bad performance if the query is somewhat complex. Added to that, the enumeration is done on the Dispatcher thread, which is also very bad for performance.

Cheers,

-- Jermoe
5/17/2012 9:08 AM | # re: Metro app development hidden gem: anonymous type binding
Why do I need to bind to the ldap server anonymously and then use the credentials provided by the user for authentication?
7/14/2012 11:19 AM | # re: Metro app development hidden gem: anonymous type binding
What happened to System.JSON??? Attempting to implement this logic in an extremely simple Metro app under VS 2012 RC. The System.JSON namespace is absolutely nowhere to be found. There's a "System.JSON (beta)" package on NuGet that apparently doesn't even target .NET 4.5 (throws the error "You are trying to install this package into a project that targets '.NETCore,Version=v4.5', but the package does not contain any assembly references that are compatible with that framework").
7/14/2012 12:06 PM | # re: Metro app development hidden gem: anonymous type binding
@sandra - look at windows.data.json
8/25/2012 2:44 PM | # re: Metro app development hidden gem: anonymous type binding
Hi - Does this work in a Gridview as i have been painstakingly trying to implement it without success. Im a bit of a newbie at programming so any help would be appreciated. Works fine on a listview

 
Please add 1 and 5 and type the answer here:

DISCLAIMER:

The opinions/content expressed on this blog are provided "ASIS" with no warranties and are my own personal opinions/content (unless otherwise noted) and do not represent my employer's view in any way.