Quantcast
Channel: C#タグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 9703

[C#/WPF] コンバーターの書き方

$
0
0

もくじ
https://qiita.com/tera1707/items/4fda73d86eded283ec4f

やりたいこと

WPFで画面を作るときにコンバーターをよく使うが、都度既存のコードからコピペしていて身についた感がなかったので、テンプレートとして持っておくために下記にメモしておく。

コンバーターの作り方

今回は、MSの公式サンプルをもとに、

  • DateTime型の値を、画面表示の際に日付の文字列に変換する
  • 日付の文字列を、プロパティget時にDateTime型の値に変換する

というコンバーターを作ってみる。

コンバーターのクラスを作る

クラス名はDateTimeConverterのように、〇〇Conveterというようにするのが慣例っぽい。
その名前で、IValueConverterインターフェースを実装した下記のようなクラスを作る。

  • Convertメソッドが「プロパティ→画面表示に反映時」の変換を記述するところ。
  • ConvertBackメソッドが「画面表示→プロパティに反映時」の変換記述するところ。
DateTimeConverter.cs
publicclassDateTimeConverter:IValueConverter{// DateTimeを「yyyy/MM/dd HH:mm:ss.fff」形式の文字列に変換publicobjectConvert(objectvalue,TypetargetType,objectparameter,CultureInfoculture){DateTimedate=(DateTime)value;returndate.ToString("yyyy/MM/dd HH:mm:ss.fff");}// 文字列をDateTimeに変換publicobjectConvertBack(objectvalue,TypetargetType,objectparameter,CultureInfoculture){stringstrValue=valueasstring;DateTimeresultDateTime;if(DateTime.TryParse(strValue,outresultDateTime)){returnresultDateTime;}returnDependencyProperty.UnsetValue;}}

※個人的経験では、ほとんどの場合「プロパティ→画面表示に反映時」に変換することしかしないので、Converterメソッドだけ使ってConvertBackメソッドはほとんど使ったことがない。

そういう場合は、ConvertBackの中身は下記のようにしておけばいい。

publicobjectConvertBack(objectvalue,TypetargetType,objectparameter,CultureInfoculture){thrownewNotImplementedException();}

画面にリソースとして登録し、それを変換したいところで使う

一番の親(今回はWindow)のリソースとして、下記のようにして登録する。

MainWIndowの一部.xaml
<Window.Resources><converter:DateTimeConverterx:Key="DateTimeConverter"/></Window.Resources>

そいつのKeyを使って、変換を行いたいコントロールにバインドしたプロパティのコンバーターとして使用する。
(今回は、ConverterParameterは別に不要だが、パラメータ渡せるということを示すために渡すだけ渡す)

MainWIndowの一部.xaml
<TextBoxGrid.Row="1"Grid.Column="2"Text="{Binding Dt, ElementName=root, Converter={StaticResource DateTimeConverter}, ConverterParameter=123}"/>

ViewModel等に、バインドするプロパティを作成して、get/setしてみる

下記のように、画面にバインドしたプロパティに

  • set(今回はDtに現在の日付をセットした)
  • get(今回はDtの値をゲットしてyyyyねんMMがつddにち形式で表示した)
MainWindow.xaml.cs
publicDateTimeDt{get{return_dt;}set{_dt=value;OnPropertyChanged(nameof(Dt));}}// テキストボックス ← プロパティprivatevoidButton_Click(objectsender,RoutedEventArgse){// setDt=DateTime.Now;}// テキストボックス → プロパティprivatevoidButton_Click_1(objectsender,RoutedEventArgse){// getAddLog(Dt.ToString("入力した日付は、yyyyねんMMがつddにち です"));}

そうすると、コンバータを通って、下記のように画面に表示される。
image.png

以上で、一通りコンバーターが使えるようになった。

コード全部

DateTimeConverter.cs
usingSystem;usingSystem.Globalization;usingSystem.Windows;usingSystem.Windows.Data;namespaceWpfApp48.converter{[ValueConversion(typeof(DateTime),typeof(string))]publicclassDateTimeConverter:IValueConverter{// DateTimeを「yyyy/MM/dd HH:mm:ss.fff」形式の文字列に変換publicobjectConvert(objectvalue,TypetargetType,objectparameter,CultureInfoculture){DateTimedate=(DateTime)value;returndate.ToString("yyyy/MM/dd HH:mm:ss.fff");}// 文字列をDateTimeに変換publicobjectConvertBack(objectvalue,TypetargetType,objectparameter,CultureInfoculture){stringstrValue=valueasstring;DateTimeresultDateTime;if(DateTime.TryParse(strValue,outresultDateTime)){returnresultDateTime;}returnDependencyProperty.UnsetValue;}}}
MainWindow.xaml
<Windowx:Class="WpfApp48.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:WpfApp48"xmlns:converter="clr-namespace:WpfApp48.converter"mc:Ignorable="d"Title="MainWindow"Height="600"Width="800"Loaded="Window_Loaded"Name="root"><Window.Resources><converter:DateTimeConverterx:Key="DateTimeConverter"/></Window.Resources><Grid><Grid.RowDefinitions><RowDefinitionHeight="5*"/><RowDefinitionHeight="1*"/></Grid.RowDefinitions><Grid.ColumnDefinitions><ColumnDefinition/><ColumnDefinition/></Grid.ColumnDefinitions><StackPanelGrid.Row="1"Grid.Column="0"><ButtonContent="1"Click="Button_Click"/><ButtonContent="2"Click="Button_Click_1"/></StackPanel><ListBoxGrid.Row="0"Grid.Column="0"Grid.ColumnSpan="2"ItemsSource="{Binding Logs, ElementName=root}"/><TextBoxGrid.Row="1"Grid.Column="2"Text="{Binding Dt, ElementName=root, Converter={StaticResource DateTimeConverter}, ConverterParameter=123}"/></Grid></Window>
MainWindow.xaml.cs
usingSystem;usingSystem.Collections.ObjectModel;usingSystem.ComponentModel;usingSystem.Windows;namespaceWpfApp48{publicpartialclassMainWindow:Window,INotifyPropertyChanged{#regionINotifyPropertyChangedpubliceventPropertyChangedEventHandlerPropertyChanged;protectedvoidOnPropertyChanged(stringpropertyName)=>this.PropertyChanged?.Invoke(this,newPropertyChangedEventArgs(propertyName));#endregion#regionLogFrameworkpublicObservableCollection<string>Logs{get;set;}=newObservableCollection<string>();publicvoidAddLog(stringlog){DateTimenow=DateTime.Now;Logs.Add(now.ToString("hh:mm:ss.fff ")+log);OnPropertyChanged(nameof(Logs));}#endregionDateTime_dt=DateTime.Now;publicMainWindow()=>InitializeComponent();privatevoidWindow_Loaded(objectsender,RoutedEventArgse){}publicDateTimeDt{get{return_dt;}set{_dt=value;OnPropertyChanged(nameof(Dt));}}// テキストボックス ← プロパティprivatevoidButton_Click(objectsender,RoutedEventArgse){Dt=DateTime.Now;}// テキストボックス → プロパティprivatevoidButton_Click_1(objectsender,RoutedEventArgse){AddLog(Dt.ToString("入力した日付は、yyyyねんMMがつddにち です"));}}}

参考

How to: Convert Bound Data
https://docs.microsoft.com/ja-jp/dotnet/desktop/wpf/data/how-to-convert-bound-data?view=netframeworkdesktop-4.8


Viewing all articles
Browse latest Browse all 9703

Trending Articles