Sergey Shishkin

on agile software development

Binding Explicit Interface in Silverlight and WP7

Yesterday I faced a quite annoying limitation of Silverlight (and of its Windows Phone 7 variant). Due to the lack of cross-assembly private reflection Silverlight’s Data Binding is unable to bind to explicitly implemented interface properties. No, I wasn’t jail-braking the phone, all I wanted to do was to bind some hierarchical data control to a LINQ Grouping. Unfortunately IGrouping<TKey,TElement> is implemented in .NET not just by internal classes (as usual, ARRRGGHH!!!) but in addition explicitly. Fine!

Others confronted with the same problem gave up by writing a public wrapper class exposing a public Key property, binding-ready. Although that solution worked I felt wrong polluting all the queries in my view model because of Silverlight data binding limitations. Another interesting approach proposed by Christopher Bennage on Stack Overflow used a Value Converter to get the Key property of a grouping. Now it looked much better in terms of separation of concerns, but the converter was hard-coded to work with IGrouping<string, MyDomainClass> only. Remember? No cross-assembly private reflection.

I tried to tweak the converter approach with no luck:

  • LINQ expression tree code generation didn’t work without Reflection.Emit.
  • Casting to IGrouping<object, object> didn’t work without co-/contra-variance in WP7

So after pulling some hair out of my head I found a rather simple solution. The Key property on the interface itself is obviously public. It is indeed possible to use reflection to get the property value if only you use a PropertyInfo from the interface, not from the implementing type.

The resulting universal value converter looks like this:

public class ExplicitPropertyConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return value == null ? null : GetPropertyValue(value, (string)parameter);
    }

    private static object GetPropertyValue(object target, string name)
    {
        return (
                from type in target.GetType().GetInterfaces()
                from prop in type.GetProperties()
                where prop.Name == name && prop.CanRead
                select prop.GetValue(target, new object[0])
            ).FirstOrDefault();
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

And the usage from XAML is like this:

<TextBlock
    Text="{Binding
        Converter={StaticResource ExplicitPropertyConverter},
        ConverterParameter=Key
    }"
    />

This is almost the right way from my perspective (the right way would if data binding in Silverlight just worked, but it’s not what Microsoft developers are accustomed to anyway). The converter itself is implemented as a cross-cutting concern, being able to bind any interface property. The only notion of this workaround is in XAML data binding, where it belongs. Of course I wish Silverlight, and especially WP7, was a real thing and not that creepy lame castrated shade of .NET, standing in my way to be more productive. Rant over…

About these ads

Written by Sergey Shishkin

18.01.2011 at 11:34

Posted in Uncategorized

2 Responses

Subscribe to comments with RSS.

  1. Thank you!!!!

    Jonathan Perl

    09.01.2012 at 01:38

    • You’re welcome!

      Sergey Shishkin

      09.01.2012 at 11:28


Comments are closed.

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: