BindingでConverterを作る!

こちらのエントリーはSilverlight Advent Calendar 2011の22日分の参加エントリーです。

さて、僭越ながら3日連続でエントリーを予定している1日目で、今回のテーマは「データバインディング」に関する内容です。

ということでまずはデータバインディングの概要から。

データバインディング概要

Silverlightにおけるデータバインディングはドキュメントの中では以下のように説明されています。

「データバインディングはSilverlightベースのアプリケーションがデータを表示し、データと対話するための簡単な方法を提供します」

ちょっと抽象的な説明でわかりずらいですよね。

Silverlightでは一般的にはUIをXAMLで表現します。XAMLで表現されたUI要素と何かしらのソースとなるデータとの間を仲介してその内容・変化を通知するメカニズムを総称してデータバインディングと呼んでいます。

これらのメカニズムはどのような形で実現されているかというと下記の図のような形で実現されています。

Binding1

まず、Bindingクラスのオブジェクトに対して、元となるデータ「Binding Source」を指定します。

Binding Sourceには任意のオブジェクト、任意のプロパティを指定することができます。

そして、次にバインディング対象となる「Binding Target」はFrameworkElementの派生クラスの依存関係プロパティに対して指定する形になります。

FrameworkElementそのものは多くのUI要素・コントロールがその派生クラスとして構成されていますので、必然的にBindingの指定が行えるということになりますね。

つまり、上記のようにTargetとSourceの間を取り持って、そのデータの内容の通信する役割を担う存在がBindingになります。

Bindingのさまざまな機能

BindingはこのようにTargetとSource間の仲介をする際に発生するさまざまな問題解決を行う機能があります。

その中でも代表的なところでは「データ型のミスマッチ」というシナリオがあります。

ご存じのとおり、.NET環境では型に対する厳密なチェック機構があります。 これはは、特に明示的に指定しない限りはビルド時点でミスマッチが検出可能で、データ型のミスマッチが起きにくい仕組みとなっています。

しかし、XAMLでは簡潔なUIの作成を支援する目的で、自由なオブジェクト・プロパティの指定が行えるメカニズムとなっています。 つまり、こうした型のミスマッチも発生する可能性があります。

これらのミスマッチがプログラミングエラーによるものの場合は、当然デバッグする必要がありますが、意図的にミスマッチを発生させることでさまざまな機能をもたらしています。

たとえば、バインディング時に指定されたデータ型のミスマッチが発生・つまり例外が発生することで「データ検証」を行ったり、強制的にデータ型にマッチするようにコントロールを加工することで「データ表現」に役立てるというシナリオなどがあります。

その中でも今回ご紹介するのが、その「データ表現」のひとつ「値コンバーターを利用した表現」をご紹介します。

値コンバーターを利用した表現

先ほどもご紹介したように、TargetとSourceのデータ型が異なっていることが明確にわかっているのであれば、その仲介となるBindingに対して値コンバーターを指定することで強制的にデータ型のミスマッチを解決しようというメカニズムになります。

図で表現すると以下のようになります。

Binding2

TargetとSourceをBindingが仲介しているのであれば、その仲介のタイミングで専用の変換ロジックを間に挟むことでこれらのミスマッチを解決しようというメカニズムになります

それでは具体的な値コンバーターの作成方法および利用方法を見ていきましょう。

値コンバーターの作成

まず、値コンバーターはあらかじめインターフェースが定義されています。

名前空間System.Windows.DataにあるIValueConverterインターフェースを実装することで作成することができます。

IValueConverterの主要なメンバーは2つ

  • Convert [Source→Targetの場合に利用されるロジック]
  • ConvertBack[Target→Sourceの場合に利用されるロジック]

になります。

SilverlightのBindingのModeプロパティ(データフローを指定するプロパティ)は既定ではOneWayとなりますので、バインディングに対して明示的にTwoWayバインディングを指定しない限り、ConvertBackは利用されません。

いずれも戻り値・引数の型などは同じになります。

Object Convert(
    Object value, //ソースもしくはターゲットの値
    Type targetType, //ソースもしくはターゲットの型
    Object parameter, //Bindingで指定されたパラメーター
    CultureInfo culture ) //カルチャー情報

値コンバーターの指定方法、サンプル

というワケで値コンバーターの指定およびサンプルコードになります。

まず、値コンバーターから

using System;
using System.Windows.Media;
using System.Windows.Data;

namespace SLAdv2011_Day22_Converter
{
    public class DoubleBrushConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            var source = System.Convert.ToInt32(value);

            var brush = new SolidColorBrush();

            if(source < 20)         brush.Color = Colors.Blue;
            else if(source < 40)    brush.Color = Colors.Green;
            else if(source < 60)    brush.Color = Colors.Yellow;
            else                    brush.Color = Colors.Red;

            return brush;
        }

        //今回は実装なし
        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}

 

取得したDouble値を強制的にintに変換して、値によって異なる色のBrushオブジェクトに変換する値コンバーターです。

今回はサンプルですのでConvertBackは実装していません。

続いて、このコンバーターを利用したサンプルです。

<UserControl x:Class="SLAdv2011_Day22_Converter.MainPage"
    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:SLAdv2011_Day22_Converter"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">
    <UserControl.Resources>
        <!--コンバーターはリソースディクショナリへ-->
        <local:DoubleBrushConverter x:Key="DBConverter" />
    </UserControl.Resources>
        
    <StackPanel>
        <Slider Name="scoreSlider" Minimum="1" />
        <StackPanel Orientation="Horizontal">
            <!--値コンバーターを利用したインジケーター-->
            <Ellipse Margin="5" Width="15" Height="15" 
                     Fill="{Binding ElementName=scoreSlider, Path=Value, Converter={StaticResource DBConverter}}" />
            <TextBlock Text="{Binding Value,ElementName=scoreSlider}" 
                     VerticalAlignment="Center" />
        </StackPanel>
    </StackPanel>

</UserControl>

今回ははUserControlのリソースディクショナリへ値コンバーターを格納し、Sliderで指定された値をEllipseを使ったインジケーターとして利用しています。

ご存じのとおり、EllipseのFillプロパティはBrush型のプロパティで、SliderのValueプロパティはDouble型のプロパティです。 こうした異なるミスマッチしたデータ型のバインディングで値コンバーターを指定することで別の新しい表現につなげることも可能です。

サンプルコードはこちら。

というワケで今日は以上になります。

今日の内容はMicrosoft Innovation Academyの「Silverlightプログラミング入門 前編」で実施しているセミナーの内容からのピックアップになりますので、よろしければ本編のセミナーもどうぞ(^^;

ツイートツイート
Facebook にシェア
このエントリーをはてなブックマークに追加
[`evernote` not found]

投稿者: Hiroyuki Mori

極東IT-Engineersの代表でMicrosoft MVP for Development Platform - Silverlightです。 普段は主にMSテクノロジ関連の開発、スピーカー、執筆などを行っています。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

* Copy This Password *

* Type Or Paste Password Here *