第0章 データバインディング 1/1《IronPython2.6》

記事一覧第1章第2章第3章第4章第5章第6章第7章余録A余録B余録C

C#.use(better, IronPython=”WPF”)
データバインディング

《著》本間りす《監修》小泉ひよ子とタマゴ倶楽部

■ 関連記事
■ 概要

データバインディング〔data binding〕は、マークアップ/分離コードで記述したデータオブジェクトに対して、洗練された一貫性のあるアクセス手段を提供します。単一のデータ項目を扱う ContentControl と、複数のデータ項目を扱う ItemsControl のどちらにも、柔軟に対処できます。
データバインディングを使うと、双方向に情報を交換できます。たとえば、コントロールを操作するだけで、インスタンス属性の値が自動的に更新されます。その逆に、インスタンス属性の値を更新した結果が、コントロールに自動的に反映されます。

《参照》データバインディングの詳細は、第2章で解説します。□

事例:データバインディング

データバインディングを利用する方法を、次の例題で紹介します。



>>ipy.exe exColorSlider.py

アプリケーションを起動すると、リスト項目には(クラス Brushes で規定された)色の名前を表示します。任意のリスト項目を選択すると、選択した項目の色をキャンバス Canvas に表示するとともに、色成分(上から順に赤/緑/青)ごとに各スライダー Slider の値が変化します。

マークアップと分離コード

マークアップでは、次の構文 {Binding Path=...} に従って、データバインディングを指定します。


<!-- exColorSlider.xaml -->
  
  
    <Slider Name="R" Value="{Binding Path=red}" ... />
    <Slider Name="G" Value="{Binding Path=green}" ... />
    <Slider Name="B" Value="{Binding Path=blue}" ... />
  
  

マークアップで記述した、各コントロール Slider は(プロパティー Name= に続く文字列と同じ名前の)インスタンス属性 R/G/B を介して、分離コードから参照できます。
ここでは、コントロール Slider のプロパティー Value= に、データバインディングを適用します。すると、結合するデータオブジェクトの(プロパティー Path= に続く文字列と同じ名前の)インスタンス属性 red/green/blue を介して、双方向に情報を交換できます。

# exColorSlider.py
class ExWindow(Window):
def selectionChanged(self, sender, e):
s = sender.SelectedItem
self.colorBox.Background = getattr(Brushes, s)
self.DataContext = ColorModel(s)

共通のプロパティー .DataContext を介して、選択したリスト項目 s から色情報 ColorModel を得ます。すると、1)リスト項目を選択したときに、2)結合するデータオブジェクトの属性を参照して、3)スライダーの値を更新します。

class ColorModel:
def __init__(self, name):
e = getattr(Brushes, name).Color
self.name = name
self.red = e.R
self.green = e.G
self.blue = e.B

このクラスでは、色成分ごとにインスタンス属性 red/green/blue を規定します。データバインディングを利用するときには、各コントロールのプロパティー Value= にこれらの属性名を指定します。たとえば、赤成分を表わすスライダー Name="R" に Value="{Binding Path=red} を指定すると、その値は ColorModel のインスタンス属性 red と結合します。

Tips

データバインディングを利用すると、コントロール間の協調作業に加えて、データオブジェクトと双方向に情報を交換できます。依存性の扱う定石〈GoFObserver パターンに代えて、オブジェクトの状態変化に呼応して、他のオブジェクトやコントロールとの整合性を確保したいときに、データバインディングは重宝します。


Last updated♪2009/07/07

《付録》exColorSlider.xaml

<!--
#    Copyright (C) 2000-2008, (^.^) piyo-piyo Tamago-Club
#
# History: WPF examples
#    2008/01/25, IronPython 1.1.1 (download)
#    2008/08/22, IronPython 1.1.2 (download)
#    2008/03/16, ver.2.0, WPF
#    2008/00/00, ver.2.1, IronPython 1.1.2 
    • >
<Slider Name="R" Value="{Binding Path=red}" Width="120" Maximum="255" /> <Slider Name="G" Value="{Binding Path=green}" Width="120" Maximum="255" /> <Slider Name="B" Value="{Binding Path=blue}" Width="120" Maximum="255" />

《付録》exColorSlider.py

# -*- coding: utf-8 -*-
#===============================================================================
#    Copyright (C) 2000-2008, 小泉ひよ子とタマゴ倶楽部
#
# History: WPF examples
#    2008/01/25, IronPython 1.1.1 (download)
#    2008/08/22, IronPython 1.1.2 (download)
#    2008/03/16, ver.2.0, WPF
#    2008/00/00, ver.2.1, IronPython 1.1.2 
#===============================================================================
from _ant import *
from System.Windows import *
from System.Windows.Media import *

## --------------------               
class ColorModel:
    def __init__(self, name):
        e = getattr(Brushes, name).Color
        self.name  = name
        self.red   = e.R
        self.green = e.G
        self.blue  = e.B

    def __str__(self):
        return "'%s'(%d,%d,%d)"%(
            self.name, self.red, self.green, self.blue)

## --------------------               
class ExWindow(Window):
    def __init__(self, Content=None, **args):
        self.InitializeComponent(Content)
        self.init()
        
    def InitializeComponent(self, Content):
        self.Content = LoadXaml(Content)
        
    def init(self):
        target = "listBox", "colorBox"
        self._Controls(target)
        for e in self.colorBrushes():
            self.listBox.Items.Add(e)            
        self.listBox.SelectionChanged += self.selectionChanged

    def _Controls(self, target):
        controls = xaml_controls(self)
        for e in target:
            setattr(self, e, controls[e])        
        
    def colorBrushes(self):
        return [e for e in dir(Brushes)
            if isinstance(getattr(Brushes, e), SolidColorBrush)]
    
    def selectionChanged(self, sender, e):
        s = sender.SelectedItem
        self.colorBox.Background = getattr(Brushes, s)        
        self.DataContext = ColorModel(s)

## --------------------               
if __name__ == "__main__":
    xaml = __file__.replace(".py",".xaml")
    win = ExWindow(
        Title=xaml,
        Width=250, Height=150,
        Content=xaml,
        )
    Application().Run(win)

## --------------------