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.
The most common use of StringFormat
in Bindings for me is to format DateTimes and Numbers.
1<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:
1<!-- ResourceDictionary in App.xaml -->
2<!-- Converter -->
3<converter:DateTimeStringFormatConverter x:Key="DateTimeStringFormatConverter" />
4
5<!-- Constants -->
6<x:String x:Key="DateFormatString">dd.MM.yyyy</x:String>
7
8<!-- View.xaml -->
9<TextBox Text="{Binding CurrentTime,
10 Converter={StaticResource DateTimeStringFormatConverter},
11 ConverterParameter={StaticResource DateFormatString}}" />
1<!-- ResourceDictionary in App.xaml -->
2<DataTemplate DataType="{x:Type vm:InfoViewModel}">
3 <v:Info />
4</DataTemplate>
5
6<!-- MainWindow.xaml -->
7<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 a 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.
1public class CustomTemplateSelector : DataTemplateSelector
2{
3 private static readonly IDictionary<Type, DataTemplate> DataTemplates;
4
5 static CustomTemplateSelector()
6 {
7 DataTemplates = new Dictionary<Type, DataTemplate>
8 {
9 { typeof(MyViewModel), Application.Current.Resources["MyDataTemplate"] as DataTemplate },
10 };
11 }
12
13 protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
14 {
15 if (item == null)
16 {
17 return null;
18 }
19
20 Type viewModelType = item.GetType();
21 return DataTemplates.ContainsKey(viewModelType) ? DataTemplates[item.GetType()] : null;
22 }
23}
1<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.