Learn Use of Converters in WPF C#

In Windows Presentation Foundation (WPF), converters serve the purpose of facilitating the binding of data between different types. They enable the transformation of data as it transitions from the source to the target within data bindings. This functionality is especially beneficial when the data must be presented in a manner that differs from its original format or when there is a mismatch between data types.

Types of Converters in WPF

  1. IValueConverter: This is the most frequently utilized converter in WPF, allowing for the conversion of a value from one type to another and vice versa.
  2. IMultiValueConverter: This converter is employed when there is a need to bind multiple values to a single property, offering a means to combine or manipulate several bound values.

When to Utilize Converters?

  1. Type Transformation: When it is necessary to convert data from one type to another (for instance, from a boolean to a visibility value).
  2. Formatting: When data requires formatting prior to being displayed (such as converting a DateTime into a specific string format).
  3. Conditional Binding: When the presentation of data is contingent upon specific conditions (for example, converting a score into a color based on its value).
  4. Localization: When data needs to be converted in accordance with cultural or regional settings.

Advantages of IValueConverter

  • Reusability: Converters can be defined once and reused across multiple bindings.
  • Separation of Concerns: They keep the logic for data transformation separate from the UI, making the code cleaner and easier to maintain.
  • Flexibility: They allow for complex data transformation and formatting without modifying the underlying data.
  • Localization and Globalization: Converters can adapt data displays according to cultural settings, making applications more user-friendly across different regions.

Advantages of MultiValue Converters

  • Integration of Values: Seamlessly merge several values into one for presentation or processing purposes.
  • Advanced Data Transformation: Execute intricate data modifications that require multiple inputs.
  • Improved Maintainability: Enhance the clarity of your XAML by delegating complex logic to the converter.

Example of IValueConverter

Step 1. Create a WPF UI Like below.

<Window x:Class="WpfValueConverter.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfValueConverter"
        mc:Ignorable="d"
        Title="MainWindow" Height="550" Width="800">
    <Window.Resources>
        <local:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
        <local:FullNameConverter x:Key="FullNameConverter"/>
        <local:ColorConverter x:Key="ColorConverter"/>
    </Window.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="300"/>
            <RowDefinition Height="40"/>
        </Grid.RowDefinitions>
        <GroupBox Header="Single Value Converter" Grid.Row="0" Margin="5">
            <StackPanel Orientation="Vertical">
                <CheckBox Content="IsTextBlock visible" Height="40" 
                          IsChecked="{Binding IsCheckedCheckBox, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
                <TextBlock Height="40" VerticalAlignment="Center" HorizontalAlignment="Center" 
                           FontSize="30" Text="Hello, World!" 
                           Visibility="{Binding IsVisible, Converter={StaticResource BooleanToVisibilityConverter}}"/>
            </StackPanel>
        </GroupBox>
        <GroupBox Header="Multi Value Converter" Grid.Row="1">
            <StackPanel Margin="20" Height="190" Orientation="Vertical">
                <TextBox Height="30" Text="{Binding FirstName, UpdateSourceTrigger=PropertyChanged}" Margin="5"/>
                <TextBox Height="30" Text="{Binding LastName, UpdateSourceTrigger=PropertyChanged}" Margin="5"/>
                <TextBlock Height="50" Margin="5" FontWeight="Bold" FontSize="30">
                    <TextBlock.Text>
                        <MultiBinding Converter="{StaticResource FullNameConverter}">
                            <Binding Path="FirstName"/>
                            <Binding Path="LastName"/>
                        </MultiBinding>
                    </TextBlock.Text>
                    <TextBlock.Foreground>
                        <MultiBinding Converter="{StaticResource ColorConverter}">
                            <Binding Path="FirstName"/>
                            <Binding Path="LastName"/>
                        </MultiBinding>
                    </TextBlock.Foreground>
                </TextBlock>
            </StackPanel>
        </GroupBox>
    </Grid>
</Window>

Window

Step 2. Create a ViewModel for the above view.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WpfValueConverter
{
    internal class MainWindowViewModel : BindableBase
    {
        private bool _IsVisible = false;
        public bool IsVisible
        {
            get { return _IsVisible; }
            set
            {
                SetProperty(ref _IsVisible, value);
            }
        }
        private bool _IsCheckedCheckBox;
        public bool IsCheckedCheckBox
        {
            get { return _IsCheckedCheckBox; }
            set
            {
                SetProperty(ref _IsCheckedCheckBox, value);
                IsVisible = value;
            }
        }
        private string _firstName;
        public string FirstName
        {
            get { return _firstName; }
            set { SetProperty(ref _firstName, value); }
        }
        private string _lastName;
        public string LastName
        {
            get { return _lastName; }
            set { SetProperty(ref _lastName, value); }
        }
        private double _DoubleTxt;
        public double DoubleTxt
        {
            get { return _DoubleTxt; }
            set
            {
                SetProperty(ref _DoubleTxt, value);
            }
        }
    }
}

Step 3. Develop classes that implement IValueConverter and IMultiValueConverter interfaces as demonstrated below.

IValueConverter

using System.Globalization;
using System.Windows;
using System.Windows.Data;
namespace WpfValueConverter
{
    public class BooleanToVisibilityConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value is bool boolean)
            {
                return boolean ? Visibility.Visible : Visibility.Collapsed;
            }
            return Visibility.Collapsed;
        }
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value is Visibility visibility)
            {
                return visibility == Visibility.Visible;
            }
            return false;
        }
    }
}

IMultiValueConverter

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

namespace WpfValueConverter
{
    public class FullNameConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            if (values != null)
            {
                return values[0] + " " + values[1];
            }
            return " ";
        }

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

    public class ColorConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            if (values != null)
            {
                if (values[0] != null && values[1] != null && 
                    !string.IsNullOrEmpty(values[0].ToString()) && 
                    !string.IsNullOrEmpty(values[1].ToString()))
                {
                    return Brushes.Red;
                }
            }
            return Brushes.Black;
        }

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

    public class FullNameColorConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            if (values.Length == 2 && values[0] is string firstName && values[1] is string lastName)
            {
                string fullName = $"{firstName} {lastName}";
                SolidColorBrush color;

                if (fullName.Length <= 10)
                {
                    color = Brushes.Green; // Short name
                }
                else if (fullName.Length <= 20)
                {
                    color = Brushes.Orange; // Medium name
                }
                else
                {
                    color = Brushes.Red; // Long name
                }

                return new Tuple<string, SolidColorBrush>(fullName, color);
            }
            return new Tuple<string, SolidColorBrush>("Invalid Name", Brushes.Black);
        }

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

Step 4. Output of converter

IValueConverter

Converter

Use of BooleanToVisibilityConverter

The Convert method converts a boolean value to a Visibility value.

Parameters

  • object value: The input value to be converted. This value is expected to be a boolean.
  • Type targetType: The target type of the binding. This parameter is usually not used in simple converters.
  • object parameter: An optional parameter that can be passed to the converter. This parameter is usually not used in this context.
  • CultureInfo culture: Provides culture-specific information. This parameter is usually not used in simple converters.

Implementation

  • if (value is bool boolean): Checks if the input value is of type bool.
    • If true, it returns Visibility. Visible if the boolean value is true, otherwise it returns Visibility. Collapsed.
    • If the input value is not a boolean, it defaults to returning Visibility. Collapsed.

MultiValueConverter

Multi value

Use of FullNameConverter

A class named FullNameConverter is designed to implement the IMultiValueConverter interface. This interface is utilized within WPF (Windows Presentation Foundation) to transform multiple values into a single value, typically for the purpose of data binding.

The Convert method is responsible for converting an array of input values into a single output value.

Parameters

  • object[] values: An array of input values that the converter receives. This array is expected to contain the first name and last name.
  • Type targetType: The target type of the binding. This parameter is usually not used in simple converters.
  • object parameter: An optional parameter that can be passed to the converter. This parameter is usually not used in this context.
  • System.Globalization.CultureInfo culture: Provides culture-specific information. This parameter is usually not used in simple converters.

Implementation

  • If (values != null): Checks if the values array is not null.
  • return values[0] + " " + values[1];: If values is not null, it concatenates the first two elements of the array (assumed to be the first name and last name) with a space in between and returns the resulting string.
  • return " ": If the value is null, it returns a single space.

Use of ColorConverter

The Convert method converts an array of input values into a single output value (a brush color).

Parameters

  • object[] values: An array of input values that the converter receives. The array is expected to contain at least two values.
  • Type targetType: The target type of the binding. This parameter is usually not used in simple converters.
  • object parameter: An optional parameter that can be passed to the converter. This parameter is usually not used in this context.
  • System.Globalization.CultureInfo culture: Provides culture-specific information. This parameter is usually not used in simple converters.

Implementation

  • if (values != null): Checks if the values array is not null.
  • if (values[0] != null && values[1] != null && !string.IsNullOrEmpty(values[0].ToString()) && !string.IsNullOrEmpty(values[1].ToString())): Checks if the first two elements of the values array are not null and not empty strings.
    • If this condition is true, it returns Brushes. Red, indicating that both values are present and valid.
    • If the condition is false, it returns Brushes. Black, indicating that one or both values are missing or invalid.