Skip to main content
Version: 11.0.0

How to Create a Custom Data Binding Converter

When one of the built-in data binding converters does not meet your conversion requirements, you can write a custom converter based on the IValueConverter interface. This guide will show you how.

info

To review the Microsoft documentation for the IValueConverter interface, see here.

info

As the IValueConverter interface was not available in .NET standard 2.0, Avalonia UI contains a copy in the Avalonia.Data.Converters namespace. You can see the API documentation about this interface, here.

You must reference a custom converter in some resources before it can be used. This can be at any level in your application. In this example, the custom converter myConverter is referenced in the window resources:

<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ExampleApp;assembly=ExampleApp">

<Window.Resources>
<local:MyConverter x:Key="myConverter"/>
</Window.Resources>

<TextBlock Text="{Binding Value, Converter={StaticResource myConverter}}"/>
</Window>

Example

This example data binding converter can convert text to specific case from a parameter:

<TextBlock Text="{Binding TheContent, 
Converter={StaticResource textCaseConverter},
ConverterParameter=lower}" />

The above XAML assumes that the textCaseConverter has been referenced in a resource.

public class TextCaseConverter : IValueConverter
{
public static readonly TextCaseConverter Instance = new();

public object? Convert(object? value, Type targetType, object? parameter,
CultureInfo culture)
{
if (value is string sourceText && parameter is string targetCase
&& targetType.IsAssignableTo(typeof(string)))
{
switch (targetCase)
{
case "upper":
case "SQL":
return sourceText.ToUpper();
case "lower":
return sourceText.ToLower();
case "title": // Every First Letter Uppercase
var txtinfo = new System.Globalization.CultureInfo("en-US",false)
.TextInfo;
return txtinfo.ToTitleCase(sourceText);
default:
// invalid option, return the exception below
break;
}
}
// converter used for the wrong type
return new BindingNotification(new InvalidCastException(),
BindingErrorType.Error);
}

public object ConvertBack(object? value, Type targetType,
object? parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}

Target Property Type

You may want to write a a custom converter that can switch the output type depending on what the target property requires. You can achieve this becuase the Convert method receives a targetType argument that you can test with the IsAssignableTo function.

In this example, the animalConverter can find an image, or a text name for a bound Animal class object:

XAML
<Image Width="42" 
Source="{Binding Animal, Converter={StaticResource animalConverter}}"/>
<TextBlock
Text="{Binding Animal, Converter={StaticResource animalConverter}}" />
AnimalConverter.cs
public class AnimalConverter : IValueConverter
{
public static readonly AnimalConverter Instance = new();

public object? Convert( object? value, Type targetType,
object? parameter, CultureInfo culture )
{
if (value is Animal animal)
{
if (targetType.IsAssignableTo(typeof(IImage)))
{
img = @"icons/generic-animal-placeholder.png"
switch (animal)
{
case Dog d:
img = d.IsGoodBoy ? @"icons/dog-happy.png"
: @"icons/dog.png";
break;
case Cat:
img = @"icons/cat.png";
break;
// etc. etc.
}
// see https://docs.avaloniaui.net/docs/guides/data-binding/how-to-create-a-custom-data-binding-converter
return BitmapAssetValueConverter.Instance
.Convert(img, typeof(Bitmap), parameter, culture);
}
else if (targetType.IsAssignableTo(typeof(string)))
{
return !string.IsNullOrEmpty(animal.NickName) ?
$"{animal.Name} \"{animal.NickName}\"" : animal.Name;
}
}
// converter used for the wrong type
return new BindingNotification(new InvalidCastException(),
BindingErrorType.Error);

}

public object ConvertBack( object? value, Type targetType,
object? parameter, CultureInfo culture )
{
throw new NotSupportedException();
}
}

More Information

info

For further guidance about how to bind images, see here.