22
30

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

WPFのデータ変換

Last updated at Posted at 2015-01-10

(これは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

22
30
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
22
30

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?