ぱぇぽぃ2 ? Blog Archive ? Python getter, setter
の続き、上手くいったので覚書に。
ObservableCollection を作って ListView で DataBinding させる。
Silverlight Dynamic Languages SDK – Discussions
ほう、こうすればいいんだ。
コレを IronPython 2.6 から使える property setter でやってみる。
{ironpythondir}/Tutorial/pyevent.py
をソースコードと同じ場所にコピー
追記と小変更
pyevent.py の import はこうすればコピー不要
import sys tutorial_path = IO.Path.GetDirectoryName(sys.executable) + "\\Tutorial" sys.path.insert(0, tutorial_path) from pyevent import *
データトリガーなんかをコードで行う方法が解らないので XAML で。
以下ソースコード
#-*- coding:utf-8 -*-
import clr
clr.AddReferenceByPartialName("PresentationCore")
clr.AddReferenceByPartialName("PresentationFramework")
clr.AddReferenceByPartialName("WindowsBase")
from System import *
from System.Windows import *
from System.Windows.Controls import *
from System.Collections.ObjectModel import *
from System.ComponentModel import *
from System.Windows.Markup import XamlReader
# Search pyevent.py
import sys
tutorial_path = IO.Path.GetDirectoryName(sys.executable) + "\\Tutorial"
sys.path.insert(0, tutorial_path)
from pyevent import *
listview_str = """<ListView
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <ListView.Resources>
        <Style x:Key="sensitive" TargetType="TextBlock">
            <Style.Triggers>
                <DataTrigger Binding="{Binding Path=show}" Value="False">
                    <Setter Property="Foreground" Value="Silver" />
                </DataTrigger>
            </Style.Triggers>
        </Style>
        <DataTemplate x:Key="tpl_show">
            <CheckBox IsChecked="{Binding Path=show}" />
        </DataTemplate>
        <DataTemplate x:Key="tpl_name">
            <TextBlock Text="{Binding Path=name}" TextTrimming="CharacterEllipsis"
                Style="{StaticResource sensitive}" />
        </DataTemplate>
    </ListView.Resources>
    <ListView.View>
        <GridView>
            <GridViewColumn Header="Show" CellTemplate="{StaticResource tpl_show}" />
            <GridViewColumn Header="Name" CellTemplate="{DynamicResource tpl_name}" />
        </GridView>
    </ListView.View>
</ListView>"""
class NotifyPropertyChangedBase(INotifyPropertyChanged):
    """
        http://sdlsdk.codeplex.com/Thread/View.aspx?ThreadId=30322
    """
    PropertyChanged = None
    def __init__(self):
        (self.PropertyChanged, self._propertyChangedCaller) = make_event()
    def add_PropertyChanged(self, value):
        self.PropertyChanged += value
    def remove_PropertyChanged(self, value):
        self.PropertyChanged -= value
    
    def OnPropertyChanged(self, propertyName):
        self._propertyChangedCaller(self, PropertyChangedEventArgs(propertyName))
class MyData(NotifyPropertyChangedBase):
    """
        use setter getter.
        IronPython 2.6 or later.
    """
    @property
    def name(self):
        return self._name
    @name.setter
    def name(self, value):
        self._name = value
        self.OnPropertyChanged("name")
    @property
    def show(self):
        return self._show
    @show.setter
    def show(self, value):
        self._show = value
        self.OnPropertyChanged("show")
class DataBindingTest(Window):
    """
        ListView DataBinding Test class
    """
    def __init__(self):
        self.data = ObservableCollection[MyData]()
        self.Resources["data"] = self.data
        self.listview = XamlReader.Parse(listview_str)
        self.listview.ItemsSource = self.data
        # Temporary Data
        datadict = {"IronPython": True,
                    "C#": False,
                    "F#": True,
                    "Python": True,
                    "Ruby": False,
                    "Perl": False,
                    "C/C++": True }
        for key in datadict.keys():
            en = MyData()
            en.name = key
            en.show = datadict[key]
            self.data.Add(en)
        self.Content = self.listview
        self.Title = "DataBindingTest"
        self.Width = 300
        self.Height = 300
        # Data Check
        self.Closed += self.on_closed
    def on_closed(self, sender, e):
        """
            Checking self.data
        """
        s = ""
        for data in self.data:
            s += "%s: %s\r\n" % (data.name, data.show)
        MessageBox.Show(s)
if __name__ == "__main__":
    a = Application()
    a.Run(DataBindingTest())
見事にデータ内容と表示が一致するようになりました。
CheckBox On Off で TextBlock の色が即座に変更されます。
Ruby だけ Off に変更してみた例

終了時に ObservableCollection の内容を確認。

CheckBox の値がそのままデータとなっていることが解ります。
IronPython でもコレが可能なんですね、2.6 正式版が待ちどおしい。
Enjoy!
