[C# / UWP] 書式やカルチャ情報を指定して、DateTime型データのバインディングができるようにする方法

こんにちは！ニアです。

今回はUWP（ユニバーサルWindowsプラットフォーム）アプリで、**DateTime**型データをバインディングする時に、**書式**や**カルチャ情報**を指定できるようにする方法を紹介します。

#1. WPFアプリにおけるDateTime型データのバインディングで、書式やカルチャ情報を指定する
その前に比較として、WPFアプリでの方法を説明します。

コントロールの**Binding**クラス（System.Windows.Data名前空間）の**StringFormat**プロパティに書式を、**ConverterCulture**プロパティにカルチャ情報を指定します。

```xml:WPFアプリにおけるDateTime型データのバインディングで、書式とカルチャ情報を指定
<TextBlock Text="{Binding 「DateTime型のデータを返すプロパティ」,
					StringFormat=「書式」, ConverterCulture=「カルチャ情報」}"/>
```

```xml:MainWindow.xaml
<Window x:Class="DateTimeTest.MainWindow"
        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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:DateTimeTest"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
	<Window.Resources>
		<Style x:Key="TestStyle" TargetType="TextBlock">
			<Setter Property="FontSize" Value="16"/>
			<Setter Property="Margin" Value="10, 5"/>
			<Setter Property="Foreground" Value="White"/>
		</Style>
	</Window.Resources>
	<Window.DataContext>
		<local:Sample />
	</Window.DataContext>
	<Grid Background="Black">
		<StackPanel>
			<!-- デフォルト -->
			<TextBlock Style="{StaticResource TestStyle}" 
					   Text="{Binding NowTime}"/>
			<!-- 書式を「yyyy年MM月dd日 HH:mm:ss」と指定した時 -->
			<TextBlock Style="{StaticResource TestStyle}"
					   Text="{Binding NowTime, StringFormat=yyyy年MM月dd日 HH:mm:ss}"/>
			<!-- カルチャ情報を「ja-JP」と指定した時 -->
			<TextBlock Style="{StaticResource TestStyle}"
					   Text="{Binding NowTime, ConverterCulture=ja-JP}"/>
			<!-- カルチャ情報を「en-US」と指定した時 -->
			<TextBlock Style="{StaticResource TestStyle}"
					   Text="{Binding NowTime, ConverterCulture=en-US}"/>
		</StackPanel>
	</Grid>
</Window>
```

```csharp:MainWindow.xaml.cs
using System;
using System.Windows;

namespace DateTimeTest {
	public partial class MainWindow : Window {
		public MainWindow() {
			InitializeComponent();
		}
	}

	public class Sample {
		public DateTime NowTime { get; set; } = DateTime.Now;
	}
}
```

![BindingDateTimeOnWPF.PNG](https://qiita-image-store.s3.amazonaws.com/0/78881/543d465b-3557-a760-a8f2-eb62a2b8d594.png)



#2. UWPアプリにおけるDateTime型データのバインディングで、書式やカルチャ情報を指定する

しかしながら、UWPアプリの**Binding**クラス（Windows.UI.Xaml.Data名前空間）には、**StringFormat**プロパティや**ConverterCulture**プロパティがありません。

代わりに、**IValueConverter**インターフェースを継承したConverterクラスを作成し、そのパラメーターに書式やカルチャ情報を渡すようにします。

IValueConverterインターフェースの**Conver**メソッドのパラメーターにある**parameter**を書式に、**language**をカルチャ情報として使用し、実装していきます。

parameterはobject型なので、**object.ToStringメソッドでstring型に変換**しておき、languageは**CultureInfoクラスのコンストラクターの引数に指定してオブジェクトを生成**しておき、それぞれを**DateTime.ToStringメソッドの引数に指定**します。

```csharp:
// valueはDateTime型データを格納したobject型変数です。
( ( DateTime )value ).ToString( parameter.ToString(), new CultureInfo( language ) )
```


```csharp:DateTimeStringConverter.cs
using System;
using System.Globalization;
using Windows.UI.Xaml.Data;

namespace DateTimeTestUWP {
	// 書式やカルチャ情報を指定して、DateTimeオブジェクトを文字列に変換します。
	class DateTimeStringConverter : IValueConverter {

		public object Convert( object value, Type targetType, object parameter, string language ) {
			// valueがDateTime型の時
			if( value != null && value is DateTime ) {
				// parameterを書式、languageをカルチャ情報として使用します。
				// parameterとlanguageが指定されている時
				if( parameter != null && language != null ) {
					return ( ( DateTime )value ).ToString( parameter.ToString(), new CultureInfo( language ) );
				}
				// parameterのみ指定されている時
				else if( parameter != null ) {
					return ( ( DateTime )value ).ToString( parameter.ToString() );
				}
				// languageのみ指定されている時
				else if( language != null ) {
					return ( ( DateTime )value ).ToString( new CultureInfo( language ) );
				}
				// 何も指定されていない時
				return value;
			}
			return null;
		}

		public object ConvertBack( object value, Type targetType, object parameter, string language ) {
			// 中略
		}
	}
}
```
作成したConverterクラスをPage.Resourcesに追加します。

```xml:ConverterクラスをPage.Resourcesに追加
<!-- local : XML名前空間 "using:DateTimeTestUWP" -->
<local:DateTimeStringConverter x:Key="DateTimeStringConverter"/>
```

コントロールの**Binding**クラスの**ConverterParameter**プロパティに書式を、**ConverterLanguage**プロパティにカルチャ情報を指定します。
（ConverterParameterに指定した値がparameterに、ConverterLanguageに指定した値がlanguageに渡されます）

```xml:UWPアプリにおけるDateTime型データのバインディングで、書式とカルチャ情報を指定
<TextBlock Text="{Binding 「DateTime型のデータを返すプロパティ」,
					Converter={StaticResource DateTimeStringConverter}
					ConverterParameter=「書式」, ConverterLanguage=「カルチャ情報」}"/>
```

```xml:MainPage.xaml
<Page
    x:Class="DateTimeTestUWP.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:DateTimeTestUWP"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">
	<Page.Resources>
		<local:DateTimeStringConverter x:Key="DateTimeStringConverter"/>
		<Style x:Key="TestStyle" TargetType="TextBlock">
			<Setter Property="FontSize" Value="16"/>
			<Setter Property="Margin" Value="10, 5"/>
			<Setter Property="Foreground" Value="{ThemeResource ApplicationForegroundThemeBrush}"/>
		</Style>
	</Page.Resources>
	<Page.DataContext>
		<local:Sample/>
	</Page.DataContext>
	<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
		<StackPanel>
			<!-- デフォルト -->
			<TextBlock Style="{StaticResource TestStyle}" 
					   Text="{Binding NowTime}"/>
			<!-- 書式を「yyyy年MM月dd日 HH:mm:ss」と指定した時 -->
			<TextBlock Style="{StaticResource TestStyle}"
					   Text="{Binding NowTime, Converter={StaticResource DateTimeStringConverter},
								ConverterParameter=yyyy年MM月dd日 HH:mm:ss}"/>
			<!-- カルチャを「ja-JP」と指定した時 -->
			<TextBlock Style="{StaticResource TestStyle}"
					   Text="{Binding NowTime, Converter={StaticResource DateTimeStringConverter},
								ConverterLanguage=ja-JP}"/>
			<!-- カルチャを「en-US」と指定した時 -->
			<TextBlock Style="{StaticResource TestStyle}"
					   Text="{Binding NowTime, Converter={StaticResource DateTimeStringConverter},
								ConverterLanguage=en-US}"/>
			
			<!-- x:Bindでバインディング -->
			<TextBlock Style="{StaticResource TestStyle}" 
					   Text="{x:Bind Path=Sample1.NowTime, Converter={StaticResource DateTimeStringConverter}, ConverterParameter=yyyy年MM月dd日 HH:mm:ss, ConverterLanguage=ja-JP}"/>
		</StackPanel>
	</Grid>
</Page>
```

```csharp:MainPage.xaml.ca
using System;
using Windows.UI.Xaml.Controls;

namespace DateTimeTestUWP {
	public sealed partial class MainPage : Page {
		public MainPage() {
			InitializeComponent();
			Sample1 = DataContext as Sample;
		}
		// x:Bind用
		public Sample Sample1 { get; set; }
	}

	public class Sample {
		public DateTime NowTime { get; set; } = DateTime.Now;
	}
}
```

これで、書式やカルチャ情報を指定して、DateTime型データをバインディングすることができました！

![実行結果（Windows 10）](https://qiita-image-store.s3.amazonaws.com/0/78881/c56828f5-8299-a6cc-cec4-99a1593f1663.png)

![実行結果（Windows 10 Mobile）](https://qiita-image-store.s3.amazonaws.com/0/78881/a60bf2ba-756d-3ec6-09c8-4143a0fc0224.png)

それでは、See you next!