UWP-Apps - First Steps [Part 1]

As a mainly WPF developer, I decided to take a look at the new Universal Windows Platform (UWP). In this post I will focus on some small differences between WPF and UWP, including StringFormat and DataTemplates.

Binding StringFormat

The most common use of StringFormat in Bindings for me is to format DateTimes and Numbers.

<TextBox Text="{Binding Date, StringFormat={}{dd.MM.yyyy}}" />

In UWP, Bindings don’t provide a StringFormat property. The solution is to create a converter that takes the desired date format as parameter. Using this converter would then look like this:

<!-- ResourceDictionary in App.xaml -->
<!-- Converter -->
<converter:DateTimeStringFormatConverter x:Key="DateTimeStringFormatConverter" />

<!-- Constants -->
<x:String x:Key="DateFormatString">dd.MM.yyyy</x:String>

<!-- View.xaml -->
<TextBox Text="{Binding CurrentTime,
                        Converter={StaticResource DateTimeStringFormatConverter},
                        ConverterParameter={StaticResource DateFormatString}}" />

DataTemplates

<!-- ResourceDictionary in App.xaml -->
<DataTemplate DataType="{x:Type vm:InfoViewModel}">
    <v:Info />
</DataTemplate>

<!-- MainWindow.xaml -->
<ContentControl Content="{Binding MainContent}" />

In WPF, I often used a ContentControl along with some DataTemplates to dynamically display content (controlled by the ViewModel). The DataTemplates would define a View for each ViewModel. For some reasons, this isn’t quite as easy in an UWP App (UWP seems to resolve Datatemplates at compile time, not at execution time like WPF). The solution is to supply a custom DataTemplateSelector class.

public class CustomTemplateSelector : DataTemplateSelector
{
    private static readonly IDictionary<Type, DataTemplate> DataTemplates;

    static CustomTemplateSelector()
    {
        DataTemplates = new Dictionary<Type, DataTemplate>
        {
            { typeof(MyViewModel), Application.Current.Resources["MyDataTemplate"] as DataTemplate },
        };
    }

    protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
    {
        if (item == null)
        {
            return null;
        }

        Type viewModelType = item.GetType();
        return DataTemplates.ContainsKey(viewModelType) ? DataTemplates[item.GetType()] : null;
    }
}
<ContentControl Content="{Binding MainContent}" ContentTemplateSelector="{StaticResource CustomTemplateSelector}" />

The CustomTemplateSelector keeps references to DataTemplates in a Dictionary. I consider directly reading them from the application resources a code smell, but I couldn’t think of an elegant solution yet.

GitHub Twitter

Codefoundry