Custom handling of HandleUnmatchedElements

Topics: Extensibility
Apr 3, 2012 at 7:51 AM

Hi all,

I am investigating a way of doing localization in my WPF app and I saw a discussion where HandleUnmatchedElements could be customized to handle my type of issue. However I'm starting to push my coding skills here and I need some hands on help on how to achieve this. The Action to be customized is found in ViewModelBinder and is defined as below:

/// <summary>
/// Allows the developer to add custom handling of named elements which were not matched by any default conventions.
/// </summary>
public static Action<IEnumerable<FrameworkElement>, Type> HandleUnmatchedElements = (elements, viewModelType) => {};

Any help is highly appreciated! Thanks in advance!

Apr 3, 2012 at 10:41 AM

Solved this myself by adding this to the bootstrapper:

      Action<IEnumerable<System.Windows.FrameworkElement>, Type> fn = (elements, viewModelType) =>
        foreach (var element in elements)
          if (element is System.Windows.Controls.TextBlock)
            var e = element as System.Windows.Controls.TextBlock;
            e.Text = _localization.GetLocalizedText(element.Name.Replace("loc_", ""));

      Caliburn.Micro.ViewModelBinder.HandleUnmatchedElements = fn;

However I am  not sure if this is how you would actually solve this. Any comments highly appreciated!

Next thing to solve is how to update language specific texts when the localization settings is changed. I am using Reactive to publish the localization change so I get the notification to my viewmodels.

Apr 3, 2012 at 12:58 PM

When handling the Reactive notification in the viewmodel I do like this to rebind all elements of interest:

      var elements = Caliburn.Micro.BindingScope.GetNamedElements(this.GetView() as System.Windows.DependencyObject).Where(x => x.Name.StartsWith("loc_"));
      ViewModelBinder.HandleUnmatchedElements(elements, this.GetType());

This works so far. I have only done basic testing on a TextBlock. Dealing with menuitems it seems to be a little bit trickier but I am going to take a look on this next.

Question: Should this be implemented on every viewmodel (maybe by extending the Screen class) or can it be handled in a smarter way?

Any refactoring tips are welcome!

Apr 4, 2012 at 9:47 AM

What did I end up with?

I extended Screen and Conductor (incl AllActive and OneActive) so localization (translation to choosen language) is automatically executed when the Reactive subscription triggers.

In my menu viewmodel I had to deal with the menuitems specifically but after that I just called base.OnLocalizeChanged and all worked out fine.