WPF’s StaticExtension versus RelativeSource

Published by tom at 10:03 PM under WPF | WPF

I have been working deeply with WPF for about 3 years now and have seen quite a few samples, blogs, etc. of WPF code. There’s one aspect I wanted to dive into today and that has to do with using StaticExtension over RelativeSource.

For example, let’s assume you want to bind a TextBlock’s Text property to it’s own Foreground property. You can do this in XAML using two different ways.

The first uses StaticExtension to retrieve the static Self property from the RelativeSource type:

<TextBlock Foreground="Red"
   Text="{Binding Foreground, RelativeSource={x:Static RelativeSource.Self}}" />

The second simply uses RelativeSource directly:

<TextBlock Foreground="Red"
   Text="{Binding Foreground, RelativeSource={RelativeSource Self}}" />

The former appears to have the benefit of reusing a single instance of RelativeSource with it’s Mode property set to Self. This, of course, implies that the latter will create new instances each time the line is processed. But this is not entirely true.

Using .NET Reflector, we can see that the ProvideValue method of RelativeSource will actually return it’s own Self static property. So effectively, a new instance of RelativeSource is created, but is not retained by any associated Bindings (as they will reference the value in the static Self property).

Ultimately, it comes down to whether StaticExtension is faster/better at providing the Self static property than the RelativeSource (via their respective ProvideValue methods). To determine this, we have to analyze the operations they perform.

Both will need to be constructed when loading the XAML, in order for their ProvideValue method to be called. Both will have their parameters analyzed/constructed in order to call the appropriate constructor/property setting.

I believe the key difference is that the StaticExtension must perform reflection on the given type in order to get the value of the specified property/field. This includes resolving any types based on the XAML namespace aliases, which can be expensive in it’s own right.

Using .NET Reflector, we can see that it’s even more complicated than that. It must also determine if the specified member name is a field or a property, using two loops. The first loop looks for a static field with the specified name. First in the specified type, then in each of the base classes. If a field with the specified name is not found, then it repeats the process looking for a static property.

Reflection is considered slow enough as it is, but presence of the two loops will only make it slower. I assume it is coded this way so that member hiding, using the new keyword, will be properly resolved.

So if you have fallen into the habit of using StaticExtension over RelativeSource, like I did, then I’d recommend you change your ways!

[KickIt] [Dzone] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]

Tags: , , , , ,

E-mail | Permalink | Trackback | Post RSSRSS comment feed 0 Responses