Three things you probably didn’t know about XAML converters #2: Passing parameters to ValueConverters

If using DataBinding to display Viewmodel properties in XAML views, you’ll quickly end up with a variety of different ValueConverters even in small projects, each of which is designed for a very specific scenario. Wouldn’t it be great to create customizable converters that can be re-used in different scenarios? Although still not very flexible, the ability of passing parameters into ValueConverters points you in this direction. In general, we have to distinguish to types of passing parameters:

Parameters per call

The first way is to specify parameters within the binding, when referencing a ValueConverter that has already been instantiating (e.g., by registering it as static resource). Unfortunately, this approach is rather limited since only one parameter of type object can be passed, and this ConverterParameter can not be bound to Viewmodel properties (since it is not implemented as DependencyProperty). In addition, binding the ConverterParameter to a static value is only possible in WPF desktop projects, since in Silverlight (and therefore in both Windows Store and Windows Phone Apps) the x:static syntax is not available.

Therefore, I’ll present a quick-and-dirty example that passes a string value to a simple BooleanToVisibilityConverter, to create an inverted boolean to visibility conversion:

public sealed class BooleanToVisibilityConverter : IValueConverter
{
	public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
	{
		if (value is bool)
		{
			bool input = (bool) value;

			if (parameter != null)
				if (parameter is string)
					if ((parameter as string).Equals("invert", StringComparison.InvariantCultureIgnoreCase))
						input = !input;

			return input ? Visibility.Visible : Visibility.Hidden;
		}

		// Fallback
		return DependencyProperty.UnsetValue;
	}
}
<Button Visibility="{Binding MyFlag, Converter={StaticResource BooleanToVisibilityConverter}, ConverterParameter=invert}" />

Now, the converter returns Visibility.Hidden if the input value is true, and Visibility.Visible if it is false.

As you can see, this seems to be an error-prone and rather inflexible way, but it still might be applicable to certain scenarios. A less limited alternative is presented in the next section.

Parameters per initalization

The idea behind this approach is to create several instances of the same ValueConverter, each with different parameters, and register all of them as static resource within the page or the App. Those can then be used throughout the page / the App without the need of passing parameters on every usage. As additional advantages, this approach allows multiple parameters to be defined and the exact data type of each parameter to be specified in advance.

To realize this approach, create one or several properties within the Converter class, that may be set during initialization:

public sealed class BooleanToVisibilityConverter : IValueConverter
{
	internal bool IsInverted { get; set; }

	public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
	{
		if (value is bool)
		{
			bool input = (bool) value;

			if (IsInverted)
				input = !input;

			return input ? Visibility.Visible : Visibility.Hidden;
		}

		// Fallback
		return DependencyProperty.UnsetValue;
	}
}

Within resources, create a separate Converter instance for each parameter combination, and provide unique keys for these instances.

<Page.Resources>
	<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" IsInverted="False" />
	<BooleanToVisibilityConverter x:Key="InvertedBooleanToVisibilityConverter" IsInverted="True" />
</Page.Resources>

They can then be referenced like “normal” converters from XAML code:

<Button Visibility="{Binding MyFlag, Converter={StaticResource InvertedBooleanToVisibilityConverter}}" />