BlackWaspTM

This web site uses cookies. By using the site you accept the cookie policy.This message is for compliance with the UK ICO law.

Windows Presentation Foundation
.NET 4.0+

WPF Data Binding - MultiBindings

The one hundred and first part of the Windows Presentation Foundation Fundamentals tutorial continues to look at data binding. This article describes how a single property can be bound to multiple data sources.

Implementing an IMultiValueConverter

Converting between the source values and the target type is similar to the translation provided by custom value converters. Instead of using the IValueConverter interface, you must create a class that implements IMultiValueConverter. The two interfaces are similar, defining one method for converting from the source to the destination and another to convert back. You can elect to implement only one method if your converter only needs to operate in one direction.

We need a converter that transforms from three double-precision floating-point numbers to a SolidColorBrush, which is the type used for a solid background colour. Add a new class named, "RgbToSolidColorBrushConverter" to the project. We'll need classes from the System.Windows.Data, System.Windows.Media and System.Globalization namespaces, so add the following using directives:

using System.Windows.Data;
using System.Windows.Media;
using System.Globalization;

Update the code for the class, as follows, to implement the interface. As you can see, this implementation is almost identical to that of IValueConverter. The key difference is the use of object arrays, rather than single objects.

public class RgbToSolidColorBrushConverter : IMultiValueConverter
{
    public object Convert(
        object[] values, Type targetType, object parameter, CultureInfo culture)
    {
    }

    public object[] ConvertBack(
        object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
    }
}

Let's implement Convert first. We need to accept three doubles and return a SolidColorBrush. The key thing to remember is that the order of the bindings within the multibinding will be preserved. We'll require that the red, green and blue elements of a colour are provided in RGB order within the array.

public object Convert(
    object[] values, Type targetType, object parameter, CultureInfo culture)
{
    var red = (double)values[0];
    var green = (double)values[1];
    var blue = (double)values[2];

    var color = Color.FromRgb((byte)red, (byte)green, (byte)blue);
    return new SolidColorBrush(color);
}

To convert back, we can read the three elements from the brush's colour and convert them to doubles before returning them in an object array:

public object[] ConvertBack(
    object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
    var color = ((SolidColorBrush)value).Color;
    return new object[] { (double)color.R, (double)color.G, (double)color.B };
}

Adding the MultiBinding

As with other data bindings that use value converters, there are three things to do in order to add the binding. The namespace must be declared, the converter added as a resource and the target property must be updated to define the binding.

To register the namespace for the custom converter, modify the Window's opening XAML tag, as follows. This declares the MultiBindingDemo namespace with the alias, demo.

<Window x:Class="MultiBindingDemo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:demo="clr-namespace:MultiBindingDemo"
        Title="MultiBinding Demo"
        Height="150"
        Width="260">

You can now define the resource, as follows:

<Window.Resources>
    <demo:RgbToSolidColorBrushConverter x:Key="RgbToBrushConverter"/>
</Window.Resources>

The last change to make is to define the MultiBinding itself. We'll add it to the Background property of the Border control. The MultiBinding element is added as the value of the property using property element syntax. The converter resource is set using the Converter attribute and the individual bindings are the content of the MultiBinding element. Should you need to, you can add value converters to one or more of the inner bindings.

Let's create the bindings, remembering the expected order is red, green, blue. Update the XAML for the Border, as follows:

<Border Grid.Column="2" Grid.RowSpan="3"
        BorderBrush="Black" BorderThickness="3"
        CornerRadius="5" Margin="3">
    <Border.Background>
        <MultiBinding Converter="{StaticResource RgbToBrushConverter}">
            <Binding ElementName="Red" Path="Value"/>
            <Binding ElementName="Green" Path="Value"/>
            <Binding ElementName="Blue" Path="Value"/>
        </MultiBinding>
    </Border.Background>
</Border>

Run the program to see the results. You should find that manipulating the Sliders alters the colour of the Border.

4 October 2014