XAML/Silverlightでデータ バインディング連載:次世代技術につながるSilverlight入門(1/3 ページ)

データの種類に応じてUI表示をカスタマイズしたい?! XAMLなら簡単。データ・バインディングとデータ・テンプレートを解説。

» 2012年12月21日 14時51分 公開
[岩永信之]
連載:次世代技術につながるSilverlight入門
業務アプリInsider/Insider.NET

powered by Insider.NET

「連載:次世代技術につながるSilverlight入門」のインデックス

連載目次

 前回説明したようなUI(ユーザー・インターフェイス)のカスタマイズを行う動機として最も多いものは、データの種類に応じた表示方法の変更だろう。この要求に対して、Silverlightではデータ・バインディングとデータ・テンプレートという非常に強力な機能を提供していて、コントロールの自作やオーナー・ドローのような作業は不要である。

 今回と次回の2回にわたって、このデータ・バインディングとデータ・テンプレートについて説明していく。

データの表示

 本稿では、サンプル・データの表示に当たって、リスト 1に示すようなクラスを用意して使うものとする。

using System.Collections.Generic;

namespace TemplateSample.DataModels
{
  public class Point
  {
    public int X { get; set; }
    public int Y { get; set; }
  }

  public class Triangle
  {
    public Point A { get; set; }
    public Point B { get; set; }
    public Point C { get; set; }

    public IEnumerable<Point> Points
    {
      get
      {
        yield return A;
        yield return B;
        yield return C;
      }
    }
  }
}


Namespace Global.TemplateSample.DataModels

  Public Class Point
    Public Property X As Integer
    Public Property Y As Integer
  End Class

  Public Class Triangle
    Public Property A As Point
    Public Property B As Point
    Public Property C As Point
    Public ReadOnly Iterator Property Points As IEnumerable(Of Points)
      Get
        Yield A
        Yield B
        Yield C
      End Get
    End Property
  End Class

End Namespace


リスト 1: サンプル・データ用のクラス(上:C#、下:VB)


 本題に入る前に、データ・バインディングやデータ・テンプレートの仕組みを使わない場合の書き方を挙げて、その問題点を説明しておこう。

テンプレートを使わない書き方

 Silverlightでも、リスト 2のように、C#やVB(Visual Basic)などのプログラム・コード中でUIを生成することも可能である。

using System.Windows.Controls;
using TemplateSample.DataModels;
 
namespace TemplateSample.Views
{
  public class NoXamlControl : ContentControl
  {
    StackPanel Panel { get; set; }
 
    public NoXamlControl()
    {
      Content = Panel = new StackPanel();
    }
 
    public void SetData(Triangle triangle)
    {
      this.Panel.Children.Clear();
 
      foreach (var p in triangle.Points)
      {
        var item = new StackPanel
        {
          Orientation = Orientation.Horizontal,
          Children =
          {
            new TextBox { Text = p.X.ToString() },
            new TextBox { Text = p.Y.ToString() },
          }
        };
        this.Panel.Children.Add(item);
      }
    }
  }
}


Imports System.Windows.Controls
Imports TemplateSample.DataModels

Namespace Global.TemplateSample.Views

  Public Class NoXamlControl
    Inherits ContentControl

    Public Property Panel As StackPanel

    Public Sub New()
      Content = New StackPanel()
      Panel = Content
    End Sub

    Public Sub SetData(triangle As Triangle)
      Me.Panel.Children.Clear()

      For Each p In triangle.Points
        Dim item As New StackPanel With {.Orientation = Orientation.Horizontal}
        item.Children.Add(New TextBox With {.Text = p.X.ToString()})
        item.Children.Add(New TextBox With {.Text = p.Y.ToString()})
        Me.Panel.Children.Add(item)
      Next
    End Sub

  End Class

End Namespace


リスト 2: プログラム・コードでのUI生成(上:C#、下:VB)


 テンプレートの仕組みを持たないUIフレームワークの場合には、このようなコードを頻繁に書くことになるだろう。複数の(特に可変長の)データをUI上に表示するために、「foreach」(C#の場合。VBでは「For Each」)などの反復ステートメントを使う。

 「foreachステートメントのような基礎的な文法だけで書けて、XAMLなどの追加の知識が必要ない」という意味で、一見すると簡単そうなコードに思える。しかし実際のところ、簡単なコードで書けるのはUIに求められる要件自体が簡素なうちだけで、実用的なUIを作ろうとするとすぐにコードが複雑化してしまう。例えば、以下のようなことを考えてみてほしい。

 この例のコードでは、SetDataメソッドを呼ぶことで、データをUIに反映させている。そこでまず問題になるのは、「データが更新されたことを確認してSetDataメソッドを呼び直す処理をどこで行うか」である。この処理を行う管理者のようなものが別途必要になる。

 また、今の作りでは、SetDataメソッドを呼ぶたびにUI要素を作り直している。部分的にしかデータを更新していない場合でもすべてのUI要素を作り直すため、無駄が多く、性能問題を引き起こす。無駄をなくすためには、以下のような仕組みが必要になる。

  • プロパティ値の更新通知を受け取って、対応する部分だけ書き換える
  • 項目の追加/削除通知を受け取って、対応するUI要素だけを生成/破棄する
  • レイアウトの結果、画面上に表示された部分だけUI要素を生成し、画面から外れたときに破棄する(=「UIの仮想化(virtualization)」と呼ぶ)

 さらに、エンド・ユーザーの操作による値の変更を元データに反映させる必要も出てくる。生成したTextBoxオブジェクトの1つ1つに対して、TextChangedイベントやLostFocusイベントを拾って、元データへの反映処理を書く必要が出てくる。

 これらの要件にきっちり対応するためには、非常に大きな手間がかかる。そこでSilverlightは(同じXAMLを基盤にするWPFやWindowsストア・アプリでも)、このような手間のかかる部分をフレームワーク内で行い、UI開発を簡単にするための仕組みとして、「データ・バインディング(data binding)」や「データ・テンプレート(data template)」という機能を提供している。

Silverlightのデータ表示機能

 リスト 2に示すようなコードによるUI生成が、Silverlightではどう変わるかを見ていこう。リスト 2と同様のことを行うには、リスト 3に示すようなXAMLコードを記述する(分離コード側の編集は不要)。

<UserControl x:Class="TemplateSample.Views.DataTemplateSampleControl"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <ItemsControl ItemsSource="{Binding Points}">
    <ItemsControl.ItemTemplate>
      <DataTemplate>
        <StackPanel Orientation="Horizontal">
          <TextBox Text="{Binding X}" />
          <TextBox Text="{Binding Y}" />
        </StackPanel>
      </DataTemplate>
    </ItemsControl.ItemTemplate>
  </ItemsControl>
</UserControl>


リスト 3: データ・テンプレートを使ってデータの表示を行う例(XAML)


 XAMLコード中のBindingマークアップ拡張の部分がデータ・バインディング、<DataTemplate>要素の部分がデータ・テンプレートである。詳細は後述していくことになるが、このXAMLコードが行っていることを概念図化すると図 1に示すようになる。

図 1: データ・テンプレートの概念図

 「表示したいデータ」「データの項目ごとにどう表示したいかを表すひな形(=データ・テンプレート)」「項目のレイアウト方法」を個別に与えて「表示結果」を得る(リスト 3のコード中ではデータは未設定で、外部から与えて使う)。

 前述のような手間のかかる処理(=プロパティ値や要素の変更/追加/削除に応じたUIの更新、エンド・ユーザー操作の元データへの反映や、仮想化など)はSilverlightのフレームワーク内で行われる。

 それではこれらの詳細について説明していこう。今回の説明はデータ・バインディングが中心となる。

       1|2|3 次のページへ

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。