nRoute - RelayConverters - Creation of local converters

2 minutes read

When developing Silverlight or WPF application we sometimes need de create converters that would be useful only in a particular view. We must then create a class and its corresponding file that will be completely useless for the rest of the application. On big projects it would lead to a huge number of converters.

The previous article was about RelayCommands, now we will see how nRoute helps in solving our problem by using RelayConverters.

RelayConverters follow the same principle as RelayCommands with a declaration of a relay in resource and an initialization done with a behavior. Enough talks, let’s code.

We will use a slightly modified version of the view models defined on the article about RelayCommands.

public class Book
{
    public long ID { get; set; }
    public string Author { get; set; }
    public string Title { get; set; }
    public int Likes { get; set; }
}
public class MainPageViewModel : ViewModelBase
{
    private readonly IEnumerable<Book> _books;

    public MainPageViewModel()
    {
        var authors = new[] {
            "Terry Pratchett",
            "Molière",
            "Shakespeare",
            "Frank Herbert",
            "Isaac Asimov"
        };

        var list = new List<Book>();
        for (int i = 0; i < 10; ++i)
            list.Add(new Book
            {
                ID = i,
                Author = authors[i % authors.Length],
                Title = "Title " + i,
                Likes = i * i * 10
            });

        _books = list;
    }

    public IEnumerable<Book> Books
    {
        get { return _books; }
    }
}

We want to display a list of book that changes following the number of people
who liked the book. If we have more than 100 likes, we’ll say that a lot of people like this
book. Under 100 likes we’ll say that not a lot of people likes it. And if we
have no likes, guess what, no one likes it. Converters provides us with a way of doing that. But creating a class just
for this is not of a big interest for the rest of the application. Therefore we
will use a RelayConverter. Here is how to declare the Xaml :

<UserControl x:Class="nRoute_RelayConverters.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
    xmlns:n="http://nRoute/schemas/2010/xaml"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">

    <UserControl.Resources>
        <n:ValueConverterRelay x:Name="BookValueConverterRelay" />
    </UserControl.Resources>

    <i:Interaction.Behaviors>
        <n:BridgeViewModelBehavior />
        <n:BridgeValueConverterBehavior ValueConverterRelay="{StaticResource BookValueConverterRelay}" />
    </i:Interaction.Behaviors>

    <StackPanel x:Name="LayoutRoot" Background="White">
        <ItemsControl ItemsSource="{Binding Books}">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal" HorizontalAlignment="Stretch">
                        <TextBlock Text="{Binding Converter={StaticResource BookValueConverterRelay}}" />
                    </StackPanel>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </StackPanel>
</UserControl>

As we can see, it really looks like the declaration of a RelayCommand. The
only difference is that until now, we have declared the converter but not
defined the method to use to convert. And for this, let’s go to the code-behind.

First we need to add a using :

using nRoute.Components;

This using gives us access to nRoute’s extension methods. One of them,
SetRelayConverter, allows us to define the conversion method used by the
RelayConverter. Here is how it is used :

[MapView(typeof(ViewModels.MainPageViewModel))]
public partial class MainPage
{
    public MainPage()
    {
        InitializeComponent();

        this.SetRelayConverter<Book, string>("BookValueConverterRelay", BookValueConverterIn);
    }

    private static string BookValueConverterIn(Book book)
    {
        if (book.Likes > 100)
            return string.Format("A lot of people likes {0} by {1} !", book.Title, book.Author);
        else if (book.Likes > 1)
            return string.Format("Not a lot of people likes {0} by {1}.", book.Title, book.Author);
        return string.Format("No one likes {0} by {1}...", book.Title, book.Author);
    }
}

SetRelayConverter is a generic function taking two typed parameters (input type parameter and output type parameter) and two parameters (the RelayConverter’s name and the conversion method to use). Finally, a little bit of code-behind for a strictly view issue, a class saved and yes it’s still MVVM.

As usual you can get the sources of the article on my skydrive.

Updated:

Leave a Comment