(これはQiitaに慣れる記事です。)
WPFいいですよねWPF。
みなさんバインディングしてますか!!!
一バインダーとしてバインディング機能の中のデータ変換について焦点を当ててみます。(WPF始めて間もない人向けだと思ってる)
WPFのデータバインディング
ViewModelとViewを関連付けるデータバインディングの主要部分は System.Windows.Data
名前空間にあります。が、C#のコードからは中のクラスを意識することはあまりないと思います。
そんなバインディングですが、バインディングソースとして存在する値を表記を変えてユーザーに伝えたい場合があります。
その1. StringFormatを使う
文字列を付加するような、複雑さを伴わない変換は手軽に実現できます。
例えば、「コレクションの要素数を表示したい」場合。
この場合、値は何らかのコレクション.Count
プロパティで取得できますが、そのまま表示されてもユーザーにとっては何を表しているのか分からないでしょう。
BindingBaseクラスに定義してあるStringFormatプロパティに書式を流し込めば、いい感じにしてくれます。
<TextBlock Text="{Binding Items.Count, StringFormat={}{0} items}"/>
出力例: 16 items
{0}
はstringクラスのFormatメソッドをお使いの方ならご存知の書式指定項目ですが、{}
はのちに続く文字列へのエスケープ的役割を担っています。とりあえず文法を無視しそうな部分につけておけばOK(だと思ってる)。
その2. コンバーターを使う
データソースの値をこねくり回す場合の方法です。
例えば、「ファイルサイズを分かりやすく表示したい」場合。
.NETでのファイル関連はSystem.IO.FileInfo
クラスあたりで取得できます。
サイズを示すLengthプロパティはlong型で、バイト数を返します。これをそのままバインディングすると、16000
なんて味気ない表示になりますね。
using System.Windows.Data
namespace BindingTest.Converters
{
class FileSizeConverter : IValueConverter
{
static readonly string[] Suffix = new string[] { "", "K", "M", "G", "T" };
static readonly double Unit = 1024;
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (!(value is long)) throw new ArgumentException("long型じゃないよ。", "value");
double size = (double)((long)value);
int i;
for (i = 0; i < Suffix.Length - 1; i++)
{
if (size < Unit) break;
size /= Unit;
}
return string.Format("{0:" + (i == 0 ? "0" : "0.0") + "} {1}B", size, Suffix[i]);
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
出力例: 15.6 KB
一気に複雑になりましたが、
-
System.Windows.Data
内のIValueConverter
インターフェースを実装するクラスを作ります。 -
Convert
メソッドでデータソース->表示データ
へ -
ConvertBack
メソッドで表示データ->データソース
へ変換を行います。 - 両メソッドとも、引数valueはobject型なので、型判定をして適切な型にキャストしてやります。
- それぞれ返り値もobject型なので、違う型への変換も可能です。
このクラスでは後者のメソッドは使わないため、バインディング先でMode=TwoWay
に設定されるなどして呼ばれた際には例外を投げるようにしてあります。
XAML内で利用する時は、
<Window xmlns:c="clr-namespace:BindingTest.Converters">
<!-- ViewModel -->
<Window.Resources>
<c:FileSizeConverter x:Key="FileSizeConverter"/>
</Window.Resources>
<TextBlock Text="{Binding Length, Converter={StaticResource FileSizeConverter}}"/>
</Window>
という感じで、(だいぶ端折った)
コンバーターを利用する際には定義した要素のx:Key
属性で指定した値を指定します。
以上、Qiitaに慣れるためのデータソース変換記事でした。
これらを駆使したデータ変換で良いWPFライフを!
※ System.Windows.Controls.BooleanToVisibilityConverter
のように組み込みで用意されているコンバーターもありますので一度調べてみることをおすすめします。
参考
http://msdn.microsoft.com/ja-jp/library/system.windows.data(v=vs.110).aspx
https://twitter.com/atst1996/status/527463457398853634