Write more generic WPF Converters
With XAML we often use Converters during a Binding to adapt the source data to the destination type. For example, the BooleanToVisibilityConverter
converts a Boolean value into a value in the Visibility
enumeration.
This mechanism is very convenient but we can find ourselves quickly with many converters of the type:
- BooleanToVisibilityConverter
- InverseBooleanConverter
- EnumerableToBooleanConverter
- etc.
Instead of creating Converters specific to each case, it is better to try to make them generic to reuse them in a maximum of cases and thus avoid their multiplication. For example, the above converters can be summarized as a single Converter: BooleanToValueConverter
. Each time the source is a Boolean expression (true equals, is null, is empty), only the output value differs. So just make it editable. For this it is possible to define properties in Converters:
public class BooleanToValueConverter : IValueConverter
{
public object TrueValue { get; set; }
public object FalseValue { get; set; }
public object DefaultValue { get; set; }
private object GetValue(bool value)
{
return value ? TrueValue : FalseValue;
}
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null)
return GetValue(false);
if (value is bool)
return GetValue((bool)value);
// Install-Package CodeFluentRuntimeClient (https://www.softfluent.com/products/codefluent-runtime-client)
// Ou replace with Boolean.TryParse(string.Format("{0}", value), out boolean)
bool boolean;
if (ConvertUtilities.TryChangeType(value, culture, out boolean))
return GetValue(boolean);
var str = value as string;
if (str != null)
return GetValue(!string.IsNullOrEmpty(str));
var enumerable = value as IEnumerable;
if (enumerable != null)
{
var enumerator = enumerable.GetEnumerator();
bool any = enumerator.MoveNext();
return GetValue(any);
}
return DefaultValue;
}
}
You can now use this Converter in different cases:
<Application.Resources>
<system:Boolean x:Key="TrueValue">True</system:Boolean>
<system:Boolean x:Key="FalseValue">False</system:Boolean>
<utilities:BooleanToValueConverter x:Key="ValueToBooleanConverter" TrueValue="{StaticResource TrueValue}" FalseValue="{StaticResource FalseValue}" DefaultValue="{StaticResource FalseValue}" />
<utilities:BooleanToValueConverter x:Key="ReverseValueToBooleanConverter" TrueValue="{StaticResource FalseValue}" FalseValue="{StaticResource TrueValue}" DefaultValue="{StaticResource TrueValue}" />
<utilities:BooleanToValueConverter x:Key="ValueToVisibilityConverter" TrueValue="{x:Static Visibility.Visible}" FalseValue="{x:Static Visibility.Collapsed}" DefaultValue="{x:Static Visibility.Visible}" />
</Application.Resources>
We now have only one converter but this one is no longer limited to a single-use case.
Do you have a question or a suggestion about this post? Contact me!