fc2ブログ

antsk blog

WPFのCommand

WPFのCommandとCommandBindingについてどうにも理解に苦しんだので記述。

Command と CommandSource



CommandとCommandSourceは下記のような関係にある。
Command.gif

つまり、

んで、これによって何がうれしいか?というと、
たとえば
・「ファイル」→「新規作成」メニュー NewMenu がある
・ツールバーに新規作成ボタン NewButton がある
・両方に NewCommand をセットする
ということをやれば、
NewCommandのCanExecuteを変更するだけで
ボタンとメニューの両方のEnable/Disableを変更できるし、
ボタンとメニューのどちらをクリックしても同じExecuteが呼び出されることになる。

……と、ここまでは理解しやすい。

CommandBinding



じゃーCommandBindingはなんなのだろう?
上記のICommandSource/Commandでひととおり完結しているんで何の役に立つんだ?ってことで悩んだ。

んで、内部処理を解析したわけではないけど、ドキュメントを見る限りだと、こーいう風につながっている。
CommandBinding.gif

そんで、たとえばこういうXAMLで

<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Window.CommandBindings>
<CommandBinding Command="ApplicationCommands.Close"
Executed="CommandBinding_Executed" />
</Window.CommandBindings>
<StackPanel>
<Button Content="CloseButton"
Command="ApplicationCommands.Close" />
</StackPanel>
</Window>

CommandSourceがコマンドを実行すると下記のように処理が走る、っぽい。
commandsequence.gif


・RoutedCommandのExecuteで、CommandManagerに問い合わせる
・CommandManagerはCommandTarget(デフォルトはフォーカスのあるコントロール)のCommandBindingsをチェック。
  ・実行したCommandが設定されてるCommandBindingがあったら、そのExecutedイベントを実行
・その後、UIツリーを順に親に向かってたどりながら上記のCommandBindingイベントを発生させていく。


……てな動きをする。と思う。

んで何の役に立つのか?



上記のような動きをすることにより、

RoutedCommandはstaticに宣言するだけでよい


・RoutedCommandには何のロジックもなく、
・CommandManagerによる検索パスによって、
 CommandTargetからたどった親要素でしかイベントが発生しない
ということになるので、
たとえばMDI子ウインドウのボタンで実行したReloadCommandが別のウインドウに影響を与えることはない。
よってstaticに1つだけあるだけでよい。

同じコマンドの発行が状況(フォーカスコントロール)によって対象が変わる


CommandBindingをリーフレベルのコントロールにつけておくと、
Commandを単に実行するだけでフォーカス位置に応じて適切なコントロールが操作される


……ってとこか?

MVVMと


MVVMパターンで、ダイアログ(新しいWindowオブジェクト)を作成して表示する類のコマンドってどうするのかなー?と思ってた。

・MVVMのサンプルで、ViewModelにCommandを定義してExecuteコールバックでViewModelのメソッドを呼ぶパターンしか見たことなかった
・ダイアログを表示するに当たってOwner = Viewに設定したいけど、ViewModelからViewが見えないので苦しい

……ってのがあったけど、そーいうのはひょっとして
・staticなRoutedCommand変数を用意して、
・WindowのCommandBindingでバインド
・Executedイベントで別Windowを作成して表示

とかで実装するのがよいのかもしれん。
続きを読む

テーマ:プログラミング - ジャンル:コンピュータ

  1. 2009/08/26(水) 00:08:35|
  2. WPF
  3. | トラックバック:1
  4. | コメント:0

ジェネリック WCFサービス

ジェネリックなベースクラスから派生したサービスは使えるか?
を見てやってみたけど、どうもうまくいかんかったので調査。

WCF の調査の為に海外のブログを見ていたとき、「ジェネリックなベースは使えない」みたいなコメントがあったので、実際に試してみました。昔は動かなかったのでしょうか?


どうやら問題になるのは「オープン」ジェネリックのようだ。

このサンプル
// サービスインターフェース
[ServiceContract]
public interface IMasterService<T> where T : class
{
[OperationContract]
T GetData(string code);
}

// ホスト登録
static void Main()
{
......
host.AddServiceEndpoint(
typeof(IMasterService<Customer>),
new NetTcpBinding(),
address);
}


だと、エンドポイントのサービスは
IMasterService<Customer>で、型Tは固まってる。

仮に
interface IMasterService 
{
T GetData<T>(string code);
}

みたいになってると、GetDataを実際に呼び出すまで型Tがわからない。
このとき、Tが「既知の型」でなかったらGetDataは失敗するはず。

テーマ:プログラミング - ジャンル:コンピュータ

  1. 2009/08/18(火) 00:35:10|
  2. .net
  3. | トラックバック:0
  4. | コメント:0

プロフィール

antsk

Author:antsk
主にC#のプログラマ。

最新記事

最新コメント

最新トラックバック

月別アーカイブ

カテゴリ

未分類 (0)
.net (1)
WPF (8)

検索フォーム

RSSリンクの表示

リンク

このブログをリンクに追加する

ブロとも申請フォーム

この人とブロともになる

QRコード

QRコード