Archive for category XAML

Generic TypeConverter for XAML

TypeConverter‘s in WPF are part of the underlying mechanism which allow you to assign values to attributes of complex types within XAML using plain strings. For example, whenever you specify Point‘s.

<LinearGradientBrush StartPoint="0,0" EndPoint="1,1">

Typically, you specify a TypeConverter for a certain type by applying the TypeConverterAttribute to it.

[TypeConverterAttribute( typeof( PointConverter ) )]
public struct Point : IFormattable

Since attribute arguments cannot use type parameters, this prevents you from specifying a generic TypeConverter for a generic class. I came across this issue while implementing a type converter to support specifying instances of my generic Interval class from XAML. The following is not possible.

// attribute argument cannot use type parameters
[TypeConverter( typeof( IntervalTypeConverter<T, TSize> ) )]
public class Interval<T, TSize>

However, you can write a non-generic TypeConverter which is capable of converting strings to several different target types. When using XAML you can obtain a IDestinationTypeProvider service through the context which is passed to the ConvertFrom method. From here you can retrieve the fully specified target type, including generic type parameters. Through reflection you can then call a Parse method on the specific type to take care of initializing an instance of the desired type. An example for Interval can be found in my library.

public override object ConvertFrom(
    ITypeDescriptorContext context,
    CultureInfo culture,
    object value )
{
    var typeProvider =
      (IDestinationTypeProvider)context.GetService( typeof( IDestinationTypeProvider ) );
    Type targetType = typeProvider.GetDestinationType();

    // ... convert to desired target type using a parsing method

    return base.ConvertFrom( context, culture, value );
}

However, it is important to note that this type provider will only work for XAML, since the IDestinationTypeProvider service is only provided by XAML’s ServiceProviderContext. It is thus not desirable to add this TypeProvider to types which work independent from XAML, like my Interval class. In addition this would require referencing the System.Xaml assembly.

How then to make XAML use this type provider without applying the attribute to the type definition? One option is applying the TypeConverter attribute on a per-property basis.

The per-property type converter technique is particularly useful if you choose to use a property type from Microsoft .NET Framework or from some other library where you cannot control the class definition and cannot apply a TypeConverterAttribute there.

However, this implies a lot of redundancy, having to apply the attribute to every property of that specific type. Using TypeDescriptor.AddAttributes() you can assign a TypeConverter at runtime.

TypeDescriptor.AddAttributes(
  typeof( Interval<,> ),
  new TypeConverterAttribute( typeof( IntervalTypeConverter ) ) );

Any subsequent TypeDescriptor.GetConverter() call will then return the converter for the specified type. Unfortunately this does not work for XAML, since XAML does not seem to take component modifications at runtime into account. Therefore, in order for this to work, we need to implement this runtime behavior ourselves. Recall that XAML does load TypeConverter‘s specified in TypeConverterAttribute‘s. We can thus use a special type converter which redirects its implementation to a converter loaded through TypeDescriptor to hook into XAML’s type conversion runtime. I implemented a RedirectTypeConverter which can be used as a base class for this exact purpose. Each of its methods first ensures the converter is initialized using TypeDescriptor, and then redirects the call to this converter. When TypeDescriptor.GetConverter( _type ) returns the redirecting type converter itself, this means no converter was specified using TypeDescriptor, hence no conversion is supported for this type.

protected RedirectTypeConverter( Type type )
{
	_type = type;
}

public override object ConvertFrom(
	ITypeDescriptorContext context,
	CultureInfo culture,
	object value )
{
	InitializeConverter();
	return _converter.ConvertFrom( context, culture, value );
}

public void InitializeConverter()
{
	if ( _converter != null )
	{
		return;
	}

	_converter = TypeDescriptor.GetConverter( _type );
	if ( _converter.GetType() == GetType() )
	{
		string message = string.Format(
		  "Conversion failed. Converter for {0} is missing in TypeDescriptor.", _type );
		throw new InvalidOperationException( message );
	}
}
class RedirectIntervalTypeConverter : RedirectTypeConverter
{
	public RedirectIntervalTypeConverter()
		: base( typeof( Interval<,> ) )
	{
	}
}

Applying this converter using TypeConverterAttribute to generic types thus allows redirecting type conversion to a converter which supports multiple target types in environments which provide information about the target type (like XAML using IDestinationTypeProvider). You only need to add the converter once, and it will be supported for all of your dependency properties using them.

TypeDescriptor.AddAttributes(
  typeof( Interval<,> ),
  new TypeConverterAttribute( typeof( IntervalTypeConverter ) ) );

Leave a comment

ViewModel Property and Command Factory

If you are familiar with the MVVM pattern, often used in WPF/XAML, you probably know what a viewmodel should look like. These classes get quite big pretty quickly. Considering that they are mainly just an adapter on your model, to be accessed by your view, they contain a lot of duplicate code. Wherever you read “duplicate”, there most likely exists a cleaner solution, so I’ll cut to the chase. What follows are two code samples with the same behavior. In the second sample I use a factory to minimize the required code. This approach has additional advantages as well as I’ll explain later.

Let’s make a ViewModel to edit this rubber duck! (This might sound familiar to you if you have read Head First’s great book on design patterns.)

Traditional implementation:

public class DuckViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private Duck m_duck;

    private bool m_canQuack;
    public bool CanQuack
    {
        get { return m_canQuack; }
        set
        {
            m_canQuack = value;
            RaisePropertyChanged("CanQuack");
        }
    }

    private Color m_color;
    public Color Color
    {
        get { return m_color; }
        set
        {
            m_color = value;
            RaisePropertyChanged("Color");
        }
    }

    private RelayCommand m_quackCommand;
    public ICommand QuackCommand
    {
        get { return m_quackCommand; }
    }

    private RelayCommand m_saveCommand;
    public ICommand SaveCommand
    {
        get { return m_saveCommand; }
    }

    public DuckViewModel(Duck duck)
    {
        m_duck = duck;
        CanQuack = duck.CanQuack;
        Color = duck.Color;

        m_quackCommand = new RelayCommand(() => Quack(), () => CanQuack());
        m_saveCommand = new RelayCommand(() => Save());
    }

    public void RaisePropertyChanged(string property)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyEventArgs(property));
        }
    }

    public void Quack()
    {
        m_duck.Quack();
    }

    public void CanQuack()
    {
        return m_duck.CanQuack;
    }

    public void Save()
    {
        m_duck.CanQuack = CanQuack;
        m_duck.Color = Color;
    }
}

Phew, that’s a whole lot to write just for two properties and two commands isn’t it? Let’s try improving this.

Factory approach:

public enum Properties { CanQuack, Color }
public enum Commands { Save, Quack }

public class DuckViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private readonly NotifyPropertyFactory<Properties> m_properties;
    private readonly CommandFactory<Commands> m_commands;

    private Duck m_duck;

    [NotifyProperty(Properties.CanQuack)]
    public bool CanQuack
    {
        get { return (bool)m_properties.GetValue(Properties.CanQuack); }
        set { m_properties.SetValue(Properties.CanQuack, value); }
    }

    [NotifyProperty(Properties.Color)]
    public Color Color
    {
        get { return m_properties.GetValue(Properties.Color) as Color; }
        set { m_properties.SetValue(Properties.Color, value); }
    }

    public DuckViewModel(Duck duck)
    {
        m_duck = duck;
        CanQuack = duck.CanQuack;
        Color = duck.Color;

        m_properties = new NotifyPropertyFactory<Properties>(this, PropertyChanged);
        m_commands = new CommandFactory<Commands>(this);
    }

    [CommandExecute(Commands.Quack)]
    public void Quack()
    {
        m_duck.Quack();
    }

    [CommandCanExecute(Commands.Quack)]
    public bool CanQuack()
    {
        return m_duck.CanQuack;
    }

    [CommandExecute(Commands.Save)]
    public void Save()
    {
        m_duck.CanQuack = CanQuack;
        m_duck.Color = Color;
    }
}

There already exist dozens of other solutions to simplify (and improve) implementing INotifyPropertyChanged. One approach is to use a base class. I prefer the factory approach, following the design principle.

Favor composition over inheritance.

To remove the literals from the PropertyChanged call lambda’s can be used. Because my approach uses reflection, the literal isn’t a problem anymore, and is traded for an enum value.

Besides solving the previously mentioned problems, the factory approach has additional advantages:

  • No more private field members required for the properties, just one for the factory.
  • As an advantage of the factory design, the view model doesn’t need to know about concrete implementations. Behavior can be added/changed inside the factory.
  • As you might have noticed, no more command members! All the commands are contained within the command factory. Yes, you can still magically bind to them, which I’ll explain in a bit!

How it works:

You might notice the similarity with my previously posted dependency property factory. I refactored the latter, and all three factories (commands, notify property and dependency property) use the same abstract base class AbstractEnumSpecifiedFactory<T>, which already handles a lot of the required behavior by using reflection. It links MemberInfo objects to the desired attributes. Concrete implementation decide which attributes it needs, and what to do with them.

To be able to still bind to the commands I created a custom Markup Extension for XAML, allowing me to do the following.

<Button Command="{m:CommandBinding {x:Static Binding:Commands.Quack}}" Content="Quack" />

This has another additional advantage that binding is done in a safe way. The CommandBinding extension uses -you guessed it- reflection to get the correct command out of the CommandFactory in the data context.

While creating the CommandBinding extension I prepared myself to optionally create a custom general Binding extension, so that the naming conventions for dependency properties can safely be ignored, and the useless property fields can be removed.

Source code can be found in my FCL Extension library in the Whathecode.PresentationFramework assembly. The NotifyPropertyFactory is located in Whathecode.System.ComponentModel.NotifyPropertyFactory and the CommandFactory is located in Whathecode.System.Windows.Input.CommandFactory.

1 Comment