WPF Localised Bindings – What to do when they just don’t seem to work :)


I am currently working on a system in Arabic (no, I don’t understand Arabic), and I bumped into an issue where Bindings were not respecting my CurrentUICulture.

Digging bit deeper (with the help of a handy decompilation tool) I found a not-so-beautiful line in FrameworkElement.cs

public static readonly DependencyProperty LanguageProperty =
DependencyProperty.RegisterAttached("Language", typeof(XmlLanguage),
_typeofThis, new FrameworkPropertyMetadata(XmlLanguage.GetLanguage("en-US"),
FrameworkPropertyMetadataOptions.Inherits | FrameworkPropertyMetadataOptions.AffectsMeasure));

As you can see, WPF does NOT respect your thread’s CurrentUICulture.

The fix is simple… finding it, on the other hand, was a nightmare.

Just override the metadata as follows:

FrameworkElement.LanguageProperty.OverrideMetadata
(typeof (FrameworkElement),
new FrameworkPropertyMetadata(XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.IetfLanguageTag)));

Hope it helps :)

Advertisements

Consuming Routed Events in WPF


In my last post I gave a brief explanation of what a RoutedEvent is all about.  In this blog post I am going to show you how to consume a custom RoutedEvent.

Let’s start off by defining a simple event (in a vanilla WPF Application using the default WPF Application project template in VS2010).

This is covered in more detail in my previous post, yet just to re-summarize:

  1. Declare the static RoutedEvent as a field in your class
  2. Register the RoutedEvent in a static constructor
  3. Raise the event… somewhere

With all that done, we can run the application and see what happens, we are interested in the console output at this point, rather than the app itself (it’s not too fancy anyway!), though if you are following along, clicking a bit on the Window so as to raise the event.

As we can see, the output is as expected.

  1. First the RoutedEvent was registered (in the static constructor)
  2. The Window was initialized (in the instance constructor)
  3. We clicked on the window… and the event was raised (in the overridden OnMouseLeftButtonDown method)

Next up, we may want to actually do something when this event happens, so we make a call to UIElement’s AddHandler method, and register a delegate of type RoutedEventHandler.

Firing it all up now and clicking, produces the following output

Which as expected is invoking our event handler.  But what if we want to register the event handler in our XAML? There is currently nothing public about our event, we therefore have to wrap our event in a standard .NET event handler, and this way expose it to XAML (after importing the namespace).

And following this, we can import the namespace, and register an event handler accordingly (we’ll use the same event handler as before).

Running and clicking on the window, now produces the following:

As you can see, the only real difference is that during the initialization phase, our XAML defined handler was also registered using out event wrapper.

That’s all there is to it.  I hope someone finds this helpful

Markup Extensions? What the…


OK, so more XAML mojo and sexiness from me :)

Markup extensions are another way of extending XAML expressiveness (like type converters), and making our XAML even more compact.  WPF already comes with many built-in markup extensions out of the box, but as with anything else, it doesn’t stop us from creating our own.

The whole idea revolves around evaluating a string at runtime (think loosely of JavaScript‘s eval() function, or JEE’s EL language), there are some exceptional cases that are actually compiled, mostly for performance reasons (though I still don’t know which specific cases these are).

If we have a look at our Object Browser, we’ll find a System.Windows.Markup namespace, with an abstract class called MarkupExtension.

We can also see a bunch of classes that derive from it.  These are our ‘Mark Up’ extensions, and exploring these will give you a good idea of what each one does.  These are also all available via the XAML language namespace, generally prefixed using x (as opposed to the WPF controls namespace which is normally the default namespace).

Let’s show an example.

Say we have a Button with an Ellipse as its content

And for some odd reason, we want to set the content property to Null.  We cannot do this using normal property element syntax, so instead, we use property attribute syntax and use a Markup Extension to inject the Null value into the content property, like so

If you’re sharp enough, you may have noticed that I have omitted the ‘Extension’ part of the name, this is allowed by WPF as a form of shorthand notation (though you can very well write the full name).

If you explorer the Object Browser further, you will also note that Binding, Static, Array, RelativeSource, etc… are all actually markup extensions.

There is nothing stopping you from defining your own markup extensions, though you need to remember to import these as a namespace prior to using them, and that they must extend from System.Windows.Markup.MarkupExtension… otherwise the XAML parser WILL complain :)

One other note.  It is also allowed to nest markup extensions ad-inifintum, the most common example being the following:

If you noticed, some parameters are prefixed (like Path=) whilst others are not.  The ones that are not are fed to the extension’s constructor as a string parameter, whilst the others are fed into the already-constructed object’s property setters.  So, in the example above, ‘RelativeSource=’ is referring to the Binding.setRelativeSource(…) setter, and feeding into it a RelativeSource object that has been constructed as new RelativeSource(“self”)… hope this clarifies a few things :)