Abstract Value Converter

Für WPF einen Konverter (IValueConverter) zu schreiben ist relativ einfach.
Einen Konverter zu schreiben, welcher dann in XAML Werte zugewiesen werden können, ist etwas schwerer.
Ich habe einen abstrakten Konverter geschrieben, welcher es ermöglicht, darauf basierend, komplexere Konverter zu schreiben zu können, welche dann direkt in XAML statische oder dynamische Parameter annehmen können.

Eine besondere Rolle hat der „Dummy Rectangle“. Dieser wird missbraucht, um während der Laufzeit festzustellen, ob die Methoden der Klasse während der Design time oder Run time aufgerufen wurden.

using System.Runtime.CompilerServices;
using System.Windows.Data;
using System.Windows.Markup;

public abstract class AValueConverter : MarkupExtension, IValueConverter
{
    protected static System.Windows.Shapes.Rectangle m_Dummy;

    static AValueConverter()
    {
        m_Dummy = new System.Windows.Shapes.Rectangle();
    }

    [MethodImpl(MethodImplOptions.NoInlining)]
    public abstract object Convert(object pValue);


    [MethodImpl(MethodImplOptions.NoInlining)]
    public virtual object Convert(object pValue, Type pTargetType, object pParameter, CultureInfo pCulture)
    {
        return Convert(pValue);
    }

    [MethodImpl(MethodImplOptions.NoInlining)]
    public override object ProvideValue(IServiceProvider pServiceProvider)
    {
        return this;
    }

    [MethodImpl(MethodImplOptions.NoInlining)]
    public virtual object ConvertBack(object pValue, Type pTargetType, object pParameter, CultureInfo pCulture)
    {
        throw new InvalidOperationException($@"This AValueConverter inheritor: ({GetType().Name}) does not support converting types backward!");
    }
}

Auf dem AValueConverter kann nun, zum Beispiel ein Bool-To-Color-Converter realisiert werden:

using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows.Media;

public class BoolToColorConverter : AValueConverter
{
    public Brush FalseBrush { get; set; } = Brushes.Red;
    public Brush TrueBrush { get; set; } = Brushes.Green;


    [MethodImpl(MethodImplOptions.NoInlining)]
    public override object Convert(object pValue)
    {
        if (DesignerProperties.GetIsInDesignMode(m_Dummy))
        {
            return FalseBrush;
        }

        if ((bool)pValue)
        {
            return TrueBrush;
        }
        else
        {
            return FalseBrush;
        }

        return FalseBrush;
    }
}

Oder zum Beispiel einen Bool-To-Visibility-Converter:

using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows;

public class BoolToVisibilityConverter : AValueConverter
{
    public Visibility FalseVisibility { get; set; } = Visibility.Hidden;
    public Visibility TrueVisibility { get; set; } = Visibility.Visible;


    [MethodImpl(MethodImplOptions.NoInlining)]
    public override object Convert(object pValue)
    {
        if (DesignerProperties.GetIsInDesignMode(m_Dummy))
        {
            return Visibility.Visible;
        }

        if ((bool)pValue)
        {
            return TrueVisibility;
        }
        else
        {
            return FalseVisibility;
        }

        return FalseVisibility;
    }
}

Diese Konverter können nun in XAML wie folgt (in Bindings) verwendet/aufgerufen werden:

xmlns:conv="clr-namespace:Path.To.ValueConvertersNamespace"
...
Property="{Binding ElementName=WpfElement, Path=Property, Converter={conv:BooleanToVisibilityConverter}}"