Saturday, 19 November 2011

ValueConverters

Introduction

If you want to databind two properties that have incompatible types, you need a piece of code in between, that converts the value from source to target type and back. This piece of code is called ValueConverter. A value converter is a class, that implements the simple interface IValueConverter with the two methods object Convert(object value) and object ConvertBack(object value).

How to implement a ValueConverter

WPF already provides a few value converts, but you will soon need to implement your own converts. To do this, add a class to your project and call it [SourceType]To[TargetType]Converter. This is a common naming for value converters. Make it public and implement the IValueConverter interface. That's all you need to do.
 
public class BoolToVisibilityConverter : IValueConverter
{
    public object Convert(object value, Type targetType, 
        object parameter, CultureInfo culture)
    {
        // Do the conversion from bool to visibility
    }
 
    public object ConvertBack(object value, Type targetType, 
        object parameter, CultureInfo culture)
    {
        // Do the conversion from visibility to bool
    }
}
 
 

How to use a ValueConverter in XAML

First thing you need to do is to map the namespace of your converter to a XAML namespace. Then you can create an instance of a value converter in the resources of the view and give it a name. Then you can reference it by using {StaticResource}
 
<Window x:Class="VirtualControlDemo.Window1"
    ...
    xmlns:l="clr-namespace:VirtualControlDemo"
    ...>
    <Window.Resources>
        <l:BoolToVisibilityConverter x:Key="converter" />
    </Window.Resources>
    <Grid>
        <Button Visibility="{Binding HasFunction, 
            Converter={StaticResource converter}}" />
    </Grid>
</Window>
 
 

Simplify the usage of ValueConvers

If you want to use a normal ValueConverter in XAML, you have to add an instance of it to the resources and reference it by using a key. This is cumbersome, because and the key is typically just the name of the converter.
A simple and cool trick is to derive value converters from MarkupExtension. This way you can create and use it in the binding like this: Text={Binding Time, Converter={x:MyConverter}}, and that is quite cool!
 
public abstract class BaseConverter : MarkupExtension
{
    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        return this;
    }
}
 
 

StringFormat Converter

The StringFormatConverter is a useful converter to control the format of an implicit string conversion of an object (e.g. if you bind a DateTime to a TextBlock ).
 
[ValueConversion(typeof(object), typeof(string))]    
public class StringFormatConverter : BaseConverter, IValueConverter    
{        
    public object Convert(object value, Type targetType, object parameter,
                      System.Globalization.CultureInfo culture)        
    {            
        string format = parameter as string;
        if (!string.IsNullOrEmpty(format))
        {                
             return string.Format(culture, format, value);
        }
        else           
        {                
            return value.ToString();
    }
 
    public object ConvertBack(object value, Type targetType, object parameter,
                    System.Globalization.CultureInfo culture)
    {
        return null; 
    }            
}
 

No comments:

Post a Comment