Blue Flower

One of key concepts at XAML-oriented development is data binding mechanism.
Binding is mediator through which property values of one or more objects are synchronized between themself.
Very important that Bindings don't hold interacting objects from garbage collection through using weak reference and subscription mechanisms!

Inheriting from class Binding is allowed, but for safety reasons overriding of method ProvideValue [which closely related with main logic] disabled. It provokes developers to use Converter pattern. Binding is a very powerful instrument, but in some cases their declaration turns verbose and awkward when used regularly, such as for localization. In this article we will discuss a simple and elegant way based on custom binding extensions to make the code much more clean and safe from memory leaks.


There are two ways for Binding declaration:

<TextBlock>
	<TextBlock.Text>
		<Binding ...>
	</TextBlock.Text>
</TextBlock>

<TextBlock Text="{Binding ...}"/>

Obvious that second method based on markup extensions looks more succinctly. At the some XAML-platforms such as WPF or classical Silverlight it is possible to create custom markup extensions by inheriting from MarkupExtension class and overriding ProvideValue method. For example, it is useful for localization.

<TextBlock Text="{Localizing AppTitle}"/>

But most simple implementation of Localizing class doesn't support hot changing of language during application run. To make this improvement is necessary, firstly, to store a link to the localized interface element, second, less obvious, anyway have application link to itself instance class Localizing to protect it from the garbage collection, and, thirdly, required to competently implement subscriptions and unsubscribe from the event to change the language.

Improper fulfillment of these conditions guarantees a memory leak if the views are created and disappear dynamically at run time, and in many cases this is true. That is, adding it would seem not the most complicated function, have to face a non-trivial themes weak links and event subscriptions. And the code will be not very easy.

Moreover MarkupExtension class don't avalaible on some another platforms, for exampple at Windows Phone Silverlight.
All this suggests the idea to use Binding like custom markup extension...

Loot at ABindingExtension class:

  
    public abstract class ABindingExtension : Binding, IValueConverter
    {
        protected ABindingExtension()
        {
            Source = Converter = this;
        }
 
        protected ABindingExtension(object source) // Source, RelativeSource, null for DataContext
        {
            var relativeSource = source as RelativeSource;
            if (relativeSource == null && source != null) Source = source;
            else RelativeSource = relativeSource;
            Converter = this;
        }
 
        public abstract object Convert(object value, Type targetType, object parameter, CultureInfo culture);
 
        public virtual object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

Noteworthy that the Binding is Converter for itself. The result is very similar behavior like at MarkupExtension class inheritance, but also remains the possibility to use standard garbage collection mechanisms of control!

Now logic for localizition looks very simple, support hot changing of a language and safe for memory leaks!


    public class Localizing : Patterns.ABindingExtension
    {
        public Localizing()
        {
            Source = LocalizationSource.Wrap;
            Path = new PropertyPath(LocalizationSource.Wrap.ActivePath);
        }

        public Localizing(string key) : this()
        {
            Key = key;
        }

        public string Key { get; set; }

        public Letter Case { get; set; }

        public override object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return LocalizationSource.Wrap[Key, culture].To(Case);
        }
    }

At XAML syntax looks clean, but there are some limitations of markup parsers on different platforms:

<!--WPF-->
<TextBlock Text="{Localizing AppTitle, Case=Upper}"/>
<TextBlock Text="{Localizing Key=AppDescription}"/>

<!--WPF, Windows Phone-->
<TextBlock Text="{m:Localizing Key=AppTitle, Case=Upper}"/>
<TextBlock Text="{m:Localizing Key=AppDescription}"/>

<!--WPF, Windows Phone, Windows Store-->
<TextBlock>
	<TextBlock.Text>
		<m:Localizing Key=AppDescription>
	</TextBlock.Text>
</TextBlock>

To get rid of the WPF on mandatory prefix m: to place the markup extension in separate assembly and Properties / AssemblyInfo.cs specify the following directives:

[assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "Aero.Markup")]
[assembly: XmlnsPrefix("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "m")]

To control the prefix name on Windows Phone or Store:

[assembly: XmlnsDefinition("clr-namespace:Aero.Markup;assembly=Aero.Phone", "Aero.Markup")]
[assembly: XmlnsPrefix("clr-namespace:Aero.Markup;assembly=Aero.Phone", "m")]

Using of ABindingExtension class does not exclude classical MarkupExtension, but in some cases first provide more secure and simple way. Of cource, all of this is not limited only by localization and suitable for many other purposes...

Complete source code

• Makeloft Foundation (Google Drive) •

• Makeloft Foundation (Dropbox) •