WPFルーティングコマンドは問題を解決しますか、それとも悪化させますか?
-
19-08-2019 - |
質問
私が理解したことから、コマンドパターンの目標は、UIの対話をアプリケーションロジックから分離することです。適切に実装されたコマンドを使用して、<!> quot; Print <!> quot;メニュー項目により、次のような一連の相互作用が発生する可能性があります。
(button) ---click executes command----> (command) ---calls Print() in app logic ---> (logic)
これにより、UIをアプリケーションロジックから分離することが推奨されます。
WPFコマンドを見てきましたが、ほとんどの場合、このパターンがどのように実装されているかがわかります。ただし、ある程度コマンドパターンを複雑化し、アプリケーションロジックからUIを分離することを思いとどまらせるような方法でそれを実装することができました。
たとえば、テキストボックスにテキストを貼り付けるためのボタンがあるこの単純なWPFウィンドウを考えてみましょう。
<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.Paste"
Executed="CommandBinding_Executed"/>
</Window.CommandBindings>
<StackPanel>
<TextBox x:Name="txtData" />
<Button Command="Paste" Content="Paste" />
</StackPanel>
</Window>
コードビハインドは次のとおりです。
namespace WpfApplication1
{
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
private void CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
{
ApplicationCommands.Paste.Execute(null, txtData);
}
}
}
コマンドから得たものは何ですか?コマンドバインディングイベントハンドラーのコードをボタンのClick
イベントに簡単に配置できるように思えます。確かに、複数のUI要素を[貼り付け]コマンドに関連付けることができ、1つのイベントハンドラーのみを使用する必要がありますが、複数の異なるテキストボックスに貼り付ける場合はどうなりますか。イベントハンドラーロジックをより複雑にするか、より多くのイベントハンドラーを記述する必要があります。だから今、私はこれを持っているように感じます:
(button) ---executes Routed Command---> (Window) ---executes command binding----(command binding)
(logic) <---calls application logic--- (event handler) <-----raises event --------------|
ここで何が欠けていますか?私にとっては間接的な層のように見えます。
解決
既に説明したことに加えて、特定の貼り付けの例で忘れていたのは、CommandTargetプロパティとCommandParameterプロパティです。貼り付けの場合、CommandTargetとして設定してTextBoxを指定できます。
これらのプロパティは、異なるコントロールから同じRoutedCommandを使用する場合に不可欠です。これらにより、コマンドが呼び出されるコンテキストに関する情報をExecutedハンドラーに提供できます。
他のヒント
概念が混乱している可能性があります。
ICommand
インターフェースはコマンドパターンをサポートします。これにより、ユーザーアクションを再利用可能なクラスに抽象化できます。
ルーティングされたコマンドは、ビジュアルツリーでハンドラーを検索する<=>の特定の実装です。これらは、多くの異なるコントロールで実装できるコマンドに特に役立ち、現在のコントロールで処理する必要があります。コピー/貼り付けを考えてください。それを処理するコントロールがたくさんある可能性がありますが、routedコマンドを使用することにより、routedコマンドシステムはフォーカスに基づいてコマンドを処理するための正しいコントロールを自動的に見つけます。
コントロールを構築する際にRoutedCommandsとRoutedUICommandsを使用することをお勧めします。たとえば、TextBoxはUndoCommandを実装し、入力Gusetureはすでに Ctrl + Z にバインドされています。 ただし、ビューモデルを構築する場合、内部設定がExecuteおよびCanExecuteであるカスタムICommandが優先されます。 DelegateCommandはPrismでこれを提供します。これにより、view / xamlデザイナーは、使用する正しいExecute / CanExecuteハンドラーではなく、コマンドのみを心配することができます。これにより、より表現力のあるビューモデルが可能になります。
ps。デリゲートコマンドは、InputBindingでまだ(エレガントに)動作しません。マイクロソフトの誰かがこれを修正してください!
これらはいくつかの点でやり過ぎになる可能性がありますが、コマンドが使用できない場合(テキストが選択されていないなど)にボタン/メニュー項目を自動的に有効/無効にできるCanExecuteのようないくつかの素晴らしい利点があります。また、コードを使用せずにBlendでコマンドを実行することもできます。これはデザイナーに最適です。