Implementing an IValueConverter in C++ /Cx for Data Binding

To create a value converter, we create a class that implements the IValueConverter interface and then implement the Convert and (optionally) the ConvertBack methods. Converters can change data from one type to another, translate data based on cultural info, or modify other aspects of the presentation.

In our sample today, we create a basic two way grade converter based on the DataBinding Metro SDK Sample App. Unlike most samples, this example shows a Two Way implementation of the IValueConverter interface and binding.

Our XAML markup is fairly simple and straight forward.

This is the MainPage.xaml

<Page
    x:Class="DataBinding.MainPage"
    IsTabStop="false"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:DataBinding"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <Grid x:Name="Input" Grid.Row="0">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto"/>
            </Grid.RowDefinitions>
            <StackPanel>
                <TextBlock Style="{StaticResource BasicTextStyle}" TextWrapping="Wrap" Text="The demonstration below shows how a custom value converter (an IValueConverter implementation) is used to control how data is displayed." />                
            </StackPanel>
        </Grid>
        
        <Grid x:Name="Output" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Row="1">
            <StackPanel>
                <Border BorderBrush="LightBlue" BorderThickness="4" CornerRadius="20" Margin="5">
                    <StackPanel Margin="5">
                        <!-- Add converter as a resource to reference it from a Binding. -->
                        <StackPanel.Resources>
                            <local:DataConverter x:Key="GradeConverter"/>
                        </StackPanel.Resources>
                        <TextBlock Style="{StaticResource BasicTextStyle}" Text="Percent grade:" Margin="5" />
                        <Slider x:Name="sliderValueConverter" Minimum="1" Maximum="100" Value="70" Margin="5"/>
                        <TextBlock Style="{StaticResource BasicTextStyle}" Text="Letter grade:" Margin="5"/>
                        <TextBox x:Name="tbValueConverterDataBound" 
                                Text="{Binding ElementName=sliderValueConverter, Path=Value, Mode=TwoWay, 
                                              Converter={StaticResource GradeConverter}}" 
                                 Margin="5" Width="150"/>
                    </StackPanel>
                </Border>
            </StackPanel>
        </Grid>  
    </Grid>
</Page>

Next, we create a local C++ class, named DataConverter. This is the class that implements the IValueConverter interface. The IValueConverter interface is found in the Windows::UI::Xaml::Data namespace.

Here is the full listing of the DataConverter.h

// This class provides a simple IValueConverter implementation
#pragma once

#include "pch.h"

using namespace Platform;
using namespace Windows::UI::Xaml::Data;
using namespace Windows::UI::Xaml::Interop;


namespace DataBinding
{
    public ref class DataConverter sealed : Windows::UI::Xaml::Data::IValueConverter
    {
    public:
        DataConverter();
        ~DataConverter();
        virtual Object^ Convert(Object^ value, TypeName targetType, Object^ parameter, String^ language);
        virtual Object^ ConvertBack(Object^ value, TypeName targetType, Object^ parameter, String^ language);
    };
}

Next, we provide the implementation of DataConverter class.

Here is the full listing of DataConverter.cpp

#include "pch.h"
#include "DataConverter.h"

using namespace DataBinding;

using namespace Platform;
using namespace Windows::Foundation;
using namespace Windows::Foundation::Collections;
using namespace Windows::Globalization::NumberFormatting;

DataConverter::DataConverter()
{
}

DataConverter::~DataConverter()
{
}

Object^ DataConverter::Convert(Object^ value, TypeName targetType, Object^ parameter, String^ language)
{
    String^ _grade = "";
    String^ _valueString = "";
    //try parsing the value to int
    int _value = ((Windows::Foundation::IPropertyValue^)value)->GetInt32();
    if (_value < 50)
        _grade = "F";
    else if (_value < 60)
        _grade = "D";
    else if (_value < 70)
        _grade = "C";
    else if (_value < 80)
        _grade = "B";
    else if (_value < 90)
        _grade = "A";
    else if (_value < 100)
        _grade = "A+";
    else if (_value == 100)
        _grade = "SUPER STAR!";
    return _grade;
}

Object^ DataConverter::ConvertBack(Object^ value, TypeName targetType, Object^ parameter, String^ language)
{
    int _value = 0;
    String^ _grade = ((Windows::Foundation::IPropertyValue^)value)->GetString();
    if (_grade == "SUPER STAR!")
        _value = 100;
    else if (_grade == "A+")
        _value = 95;
    else if (_grade == "A")
        _value = 85;
    else if (_grade == "B")
        _value = 75;
    else if (_grade == "C")
        _value = 65;
    else if (_grade == "D")
        _value = 55;
    else if (_grade == "F")
        _value = 45;

    return _value; 
}

That’s it. Our sample is now ready.

Enjoy!!

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>