第3章 Command パターン 4/4, IronPython
IronPython で学ぶ WPF プログラミングの世界《IronPython2.6》
《著》森こねこ・後藤いるか・小粒ちゃん《監修》小泉ひよ子とタマゴ倶楽部
第1版♪1995/07/02 ● 第2版♪2003/01/29 ● 第3版♪2008/04/28
■ 概要
WPF の特徴を活かして、デザインパターン
イベントに呼応するアクションを規定したいときには〈GoF〉Command パターンを導入します。すると、密接に関係する「イベント/アクション」対を、再利用可能な「部品」として扱えます。
《Note》IronPython1.x 用に作成したセミナー課題を、IronPython2.6 で再構成しました。
ソースとターゲットとの関係は
ルーティングイベントハンドラー Execute では、2つのオブジェクトを参照できます。
Execute | note |
---|---|
引数 sender | 実際にイベントハンドラーが起動されたオブジェクト |
プロパティー .Source | 最初にイベントが発生したオブジェクト |
ここで、イベントが発生したオブジェクトと、それを処理するオブジェクトが同じときには、sender/.Source は同じものを参照します。
たとえば、ボタン〔Red〕をクリックすると、次のように出力されるので、
>ipy.exe CommandToolBar.py sender: System.Windows.Controls.Button: Red Source: System.Windows.Controls.Button: Red ...
ソース/ターゲットはともに、ボタン Button になるのが分かります。
# routedCommandToolBar2.py
class ExWindow(Window):
def init(self):
...
for content, command, toolBar in [
...
self.CommandBindings.Add(binding) # (@.@) here goes...
そこで、ターゲットをボタン button から、ウィンドウ self に変更すると、
class PaintColor(RoutedCommand):
def Execute(self, sender, e):
print "sender:", sender
print "Source:", e.Source
e = e.Source.Content # (@.@) here goes...
self.panel.Background = getattr(Brushes, e)
イベントハンドラー Execute では、それを呼び出したオブジェクト sender に代えて、イベントが発生したオブジェクト e.Source から、必要な情報を獲得できます。すると、
>ipy.exe CommandToolBar2.py CommandToolBar.xaml sender: IronPython.NewTypes.System.Windows.Window_2 Source: System.Windows.Controls.Button: Red ...
Execute | note | control |
---|---|---|
引数 sender | 実際にイベントハンドラーが起動されたオブジェクト | Window |
プロパティー .Source | 最初にイベントが発生したオブジェクト | Button |
ソースはボタンに、ターゲットはウィンドウになるのが分かります。つまり、階層構造の末端にあるボタンから、その頂点にあるウィンドウまで遡って、ルーティングイベントハンドラーが起動されたことになります。
《付録》routedCommandToolBar.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
-
- >
《付録》routedCommandToolBar.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 import * from System.Windows import * from System.Windows.Controls import * from System.Windows.Input import * from System.Windows.Media import * from System.Windows.Media.Imaging import * from System.Windows.Shapes import * clr.AddReference("System.Windows.Forms") from System.Windows.Forms import OpenFileDialog ## -------------------- # Command::ConcreteCommand class FileOpen(RoutedCommand): def __init__(self, panel): self.panel = panel def Execute(self, sender, e): dialog = OpenFileDialog() dialog.ShowDialog() e = dialog.FileName.split("\\")[-1] brush = ImageBrush( ImageSource=BitmapImage(Uri("Flags/%s"%e, UriKind.Relative)) ) self.panel.Children.Add(Rectangle( Width=50, Height=50, Fill=brush, )) def CanExecute(self, sender, e): e.CanExecute = True ## -------------------- # Command::ConcreteCommand class FileClose(RoutedCommand): def __init__(self, window): self.window = window def Execute(self, sender, e): self.window.Close() def CanExecute(self, sender, e): e.CanExecute = True ## -------------------- # Command::ConcreteCommand class PaintColor(RoutedCommand): def __init__(self, panel): self.panel = panel def Execute(self, sender, e): e = sender.Content self.panel.Background = getattr(Brushes, e) def CanExecute(self, sender, e): e.CanExecute = True ## -------------------- # Command::Client 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 = "toolBarTray", "panel", self._Controls(target) target = "fileToolBar", "colorToolBar", for e in self.toolBarTray.ToolBars: if e.Name in target: setattr(self, e.Name, e) for content, command, toolBar in [ ("Open...", FileOpen (panel=self.panel), self.fileToolBar ), ("Close" , FileClose (window=self) , self.fileToolBar ), ("Red" , PaintColor(panel=self.panel), self.colorToolBar), ("Green" , PaintColor(panel=self.panel), self.colorToolBar), ("Blue" , PaintColor(panel=self.panel), self.colorToolBar), ]: button = Button( Content=content, Command=command, ) binding = CommandBinding( command, command.Execute, command.CanExecute) button.CommandBindings.Add(binding) toolBar.Items.Add(button) def _Controls(self, target): controls = xaml_controls(self) for e in target: setattr(self, e, controls[e]) ## -------------------- if __name__ == "__main__": xaml = __file__.replace(".py",".xaml") win = ExWindow( Title=__file__, Width=260, Height=120, Content=xaml, ) Application().Run(win) ## --------------------