==WPF アクション==
[[WPF][.Net][Silverlight][Universal Windows Platform][C#]]
{{amazon|4798114200}}
b.Click +=
delegete { MessageBox.Show("Clicked!"); }
<<blockquote>>このコードはうまく機能するように見えるが、クリックされているのはボタンそのものではなく、ボタンの表示を構成する要素<</blockquote>>
*WPFではこれをシームレスに機能させるためにルーティングイベントという概念を導入
====ルーティングイベント====
delegete { MessageBox.Show("Clicked!"); }
*コンテンツとしてボタンを含むように変更した場合、内側もしくは外側のいずれかのボタンをクリックするとイベントが発生する
<<blockquote>>イベントの合成は、イベントだけでなく、アクション処理のすべての側面に影響を与える<</blockquote>>
===疎結合===
*Buttonのイベントを見ると、直接的なマウスイベント(MouseUp,MouseDownなど)とClickイベントの両方をサポートすることが分かる
*Clickはマウスイベントよりも上位に位置する抽象概念(フォーカスがある状態でスペースキーや規定ボタンである場合Enterキー押下で発生する)
*Clickはセマンティック(意味的)イベントで、マウスイベントは、フィジカル(物理的)イベント
<<blockquote>>Clickイベントに対するコードを記述することは、特定の入力に縛られない、ボタンに縛られない(クリック可能なコンポーネントにのみ依存する)という利点がある<</blockquote>>
*ただし、イベント自体はメソッドの実装を特定のシグネチャにすることが要求される
=====Button.Clickのデリゲート=====
public delegate void RoutedEventHandler(object sender,RoutedEventArgs e);
<<blockquote>>WPFの目標の一つは密接に結合されたフィジカルイベントから完全にセマンティックな通知までの幅広いアクションを許容すること<</blockquote>>
====コマンド====
*疎結合を許容することでコントロールを劇的に変化させるテンプレートを記述することが可能となる
=====Closeコマンドに結び付けられたボタンを追加する=====
*ウィンドウを閉じるためのクロムを追加するウィンドウ用テンプレートを記述できる
<<ControlTemplate TargetType="{x:Type Window}">> <<DocPanel>> <<StatusBar DockPanel.Dock="Buttom">> <<StatusBarItem>> <<Button Command="{x:Static ApplicationCommands.Close}">>
閉じる
<</Button>> <</StatusBarItem>> <</StatusBar>> <</DocPanel> > <</ControlTemplate>>
*その後、ウィンドウにコマンドバインディングを追加することで、任意のコンポーネントがCloseコマンドを発行したときにウィンドウが閉じるようにすることが可能
public MyWindow() {
*コマンドはWPFにおける最も疎結合なアクションモデルを表す
*コマンドはアクションのソース(ボタンなど)とアクションのハンドラからの完全な抽象化を提供
<<blockquote>>アプリケーションを破壊せずに全く異なるコントロールを使用するようにスタイルの変更が可能となる<</blockquote>>
===宣言型アクション===
*コマンドと疎結合が導入されたことで、ソフトウェアが意図を宣言するモデルへと向かうことがわかる
*WPFの主要な基盤は宣言型プログラミングという考え方
*視覚要素、UIレイアウトに加え、アプリケーションロジックの大半をマークアップで指定することが可能
<<blockquote>>宣言型ロジックは、宣言形式の周囲で、ユーザーにツールを提供することによりエクスペリエンスを向上させたり、より高度なサービスをシステムで提供したりできるという点できわめて有効<</blockquote>>
=====アクションの処理方法によって、宣言型プログラミングのサポートレベルはことなる=====
{|class="wikitable"
*グループボックスと複数のボタンを含むウィンドウ
<<Window ...
PreviewMouseRightbuttonDown="WindowPreviewRightButtonDown"
MouseRightButtonDown="WindowRightButtonDown"
>> <<GroupBox
PreviewMouseRightbuttonDown="GroupBoxPreviewRightButtonDown"
MouseRightButtonDown="GroupBoxRightButtonDown"
>> <<StackPanel>> <<Button>>ボタン1<</Button>> <<Button
PreviewMouseRightbuttonDown="ButtonTwoPreviewRightButtonDown"
MouseRightButtonDown="ButtonTwoRightButtonDown"
>>
ボタン2
<</Button>> <</StackPanel>> <</GroupBox>> <</Window>>
*イベントハンドラでイベント名を出力
void ButtonTwoPreviewRightButtonDown(object sender,MouseButtonEventArgs e) {
}
<<blockquote>>WPFはルーティングという概念をイベントに含めるように.NETイベントモデルを拡張し、それにより要素の合成を可能にする。ほかのアクション処理機構は、すべてこの基盤イベントルーティングモデル状に構築される<</blockquote>>
==コマンド==
*WPFのほとんどのイベントは、各コントロールの実装の詳細に結びついている
====イベントでの実装例====
*まず必要なのは、プログラムを終了するためのメニュー
<<MenuItem Hader="ファイル(_F)">> <<MenuItem Header="終了(_X)" Click="ExitClicked"/>> <</MenuItem>>
*次に分離コードでイベントハンドラを実装
void ExitClicked(object sender, RouteEventArgs e) {
}
*この方法はうまく機能するが、アプリケーションを終了するハイパーリンクも加えてみる
<<TextBlock>> <<Hyperlink Click="ExitClicked">>終了<</Hyperlink>> <</TextBlock>>
*ここでは様々なことが仮定されている
**シグネチャが、Hyperlink.Clicked と互換性があること
*コマンドの実装を定義する
*コマンドのトリガを作成する
<<blockquote>>WPFのコマンドシステムの基盤になるのは、[http://msdn.microsoft.com/ja-jp/library/system.windows.input.icommand(v=vs.110).aspx ICommand]インターフェース<</blockquote>>
public interface ICommand {
event EventHandler CanExecuteChanged;
}
====マークアップとバインド====
<<MenuItem Hader="ファイル(_F)">> <<MenuItem Header="終了(_X)">> <<MenuItem.Command>> <<l:Exit />> <</MenuItem.Command>> <</MenuItem>> <</MenuItem>>
:
<<TextBlock>> <<Hyperlink>>終了 <<Hyperlink.Command><><l:Exit /><></Hyperlink.Command>> <</Hyperlink>> <</TextBlock> >
====機能セットの発行====
*コマンドは複数の場所から利用されることが一般的
*ICommand をフィールド型とすることで、Exitの実装を完全にプライベートにできる利点
*これでExitをプライベートクラスとしてマークし、静的フィールドにバインドするようにマークアップを変更できる
<<MenuItem Hader="ファイル(_F)">> <<MenuItem Header="終了(_X)" Command="{x:Static l:Window1.ExitCommand}">> <</MenuItem>><<blockquote>>こうすることで、ウィンドウでコマンドを公開することで、機能セットを発行できる。<</blockquote>>
====変更====
*現在Exitはどこからでも呼び出すことができ、アプリケーションを終了する
Keyboard.FocusedElement.RaiseEvent(e);
}
<<blockquote>>ここからコマンドバインディングという概念が生まれる<</blockquote>>
====コマンドバインディング====
*コマンドバインディングとは、コマンドの実装を、そのコマンドの身元から切り離す機能
}
}
<<blockquote>>このケースでは、Exitコマンドは要素ツリーでExecuteイベントを発生させ、Windowがそのイベントをリッスンして対応できるようにする<</blockquote>>
#メニュー項目がクリックされる
#MenuItemがコマンドでExecuteを呼び出す
====RoutedCommand====
*この方法で、入力バインディング、パラメータ、およびその他の機能をサポートするように基盤のICommandモデルを拡張することも可能
<<blockquote>>ただしフレームワークには、これらのほとんどを処理する組み込みのユーティリティクラス、RoutedCommand がすでに含まれている<</blockquote>>
*ルーティングコマンドは、コマンドの実装をコマンドの身元から完全に分離する
*コマンドの定義は静的つまり、コマンドの定義は、コマンドの身元を提供する一種のトークンに過ぎない
====InputBindingsプロパティ====
*InputBindingsプロパティを使用して入力ジェスチャをマップできる
<<Window x:Class="..." :>> <<Window.InputBindings>> <<KeyBinding Key="A" Modifires="Contorol" Command="{x:Static l:Window1.ExitCommand}" />> <</Window.InputBindings>> <</Window>>
====セキュアコマンド====
*切り取り、コピー、貼り付けなどの一部コマンドはセキュリティに影響を与える
*システムがこれらの操作をユーザーによって要求された場合のみに実行することを保証するために、RoutedCommandは、ユーザーによって開始されたかどうかを追跡可能
<<blockquote>>一般にアプリケーションロジックはイベントハンドラではなく、コマンドの観点で実装することが推奨される。イベントハンドラが必要なケースの多くはトリガーを使用したほうがうまく処理できる。<</blockquote>>
===コマンドとデータバインディング===
*コマンドを使用する場合のもっとも強力な機能はデータバインディングの統合
*コマンドを使用することでデータ駆動型のロジックも可能となる
====ドライブ内のファイルをリストするアプリケーション例====
<<Window x:Class="..." :>> <<ListBox Margin="2" Name="_files">> <<ListBox.ItemTemplate>> <<DataTemplate>> <<TextBlock Text="{Binding Path=Name}" /> > <</DataTemplate>> <</ListBox.ItemTemplate>> <</ListBox>> <</Window>>
*分離コードで、ItemSourceプロパティにファイルのリストを代入
public partial class DataAndCommands : Window {