2012-12-12 20 views
12

時には複雑な方法を何度も使用したが、最も簡単な方法を忘れていた。WPFでコマンドをバインドする方法

私はコマンドバインディングを行う方法を知っていますが、私は常に同じアプローチを使用します。

ICommandインターフェイスを実装するクラスを作成し、ビューモデルからそのクラスの新しいインスタンスを作成し、魅力的に動作します。

この

は私が

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
     DataContext = this;    
     testCommand = new MeCommand(processor); 
    } 

    ICommand testCommand; 

    public ICommand test 
    { 
     get { return testCommand; } 
    } 
    public void processor() 
    { 
     MessageBox.Show("hello world"); 
    } 
} 

public class MeCommand : ICommand 
{ 
    public delegate void ExecuteMethod(); 
    private ExecuteMethod meth; 
    public MeCommand(ExecuteMethod exec) 
    { 
     meth = exec; 
    } 

    public bool CanExecute(object parameter) 
    { 
     return false; 
    } 

    public event EventHandler CanExecuteChanged; 

    public void Execute(object parameter) 
    { 
     meth(); 
    } 
} 

bindingコマンドのために使用されるコードですが、私はこれを行うための基本的な方法を知りたい、何の第三者には、新しいクラスの作成をdllをしません。単一のクラスを使用して、この単純なコマンドバインディングを実行します。実際のクラスはICommandインターフェイスから実装し、作業を行います。

答えて

13

Prismはすでに、私はそれがサードパーティとして考えられているかわからないMicrosoft.Practices.Prism.Commands.DelegateCommand

を提供します。少なくともそれは公式でMSDNで文書化されています。

copy、pasteなどのネイティブビルドコマンドでは、ICommandインターフェイスが実装されています。 IMHOオープン(延長)/クローズ(変更)原則に従います。独自のコマンドを実装することができます。


WPF司令はhere、抜粋を文書として更新

...

WPFは、事前定義されたコマンドのセットを提供します。 Browse、Return、および BrowseForward、Play、Stop、およびPauseを参照してください。

コマンドライブラリクラスのコマンドがニーズを満たしていない場合は、 独自のコマンドを作成できます。 カスタムコマンドを作成するには2通りの方法があります。 1つは、最初から始めて、 ICommandインターフェイスを実装することです。他の方法ではより一般的なアプローチ,はRoutedCommandまたはRoutedUICommandを作成することです。

私はRoutedCommandモデルを最初に試して、ICommandを実装しました。 RoutedCommandの

<CommandBinding Command="{x:Static custom:Window1.CustomRoutedCommand}" 
        Executed="ExecutedCustomCommand" 
        CanExecute="CanExecuteCustomCommand" /> 

結合

サンプルXAMLはするRoutedEvent異なりません。これは、より良いボタンの 'Clicked'イベントハンドラのようです。これは目的に役立ちます。アプリケーションロジックをビューから分離するが、DependencyPropertyまたはコードビハインドを添付する必要がある。

個人的に私のICommandを実装するだけでもっと快適になります。

+1

これは間違いなく第三者とみなされます。私はthirsdパーティーに対する恨みを持っていません。私はGalaSoft MVVMを使用していますが、私は単純で基本的な実際の方法を知りたいのです。とにかく、ありがとう。 – MegaMind

+1

質問を実際に読んだことのある唯一の男であることを賞賛しました。 – psycho

+0

@psycho私の痛みを理解する唯一の男であるという建設的なコメント。 :-) – MegaMind

0

まあ、あなたはほとんどそれを持っています。 CanExecute()がtrueを返すようにしてください。そうしないと、コードは実行されません。 (私はそれが実際になると思うが、まだ)。また、「NotifyPropertyChanged( 'yourCommand')」を

public ICommand test 
    { 
     get { return testCommand; } 
     set { testCOmmand = value; NotifyPropertyChanged("test"); } 
    } 

ここに追加してください。

test = new MeCOmmand(); DataContext = this;あなたはVSでコードを実行せずに何をすべきかから判断すると

+0

このコマンドの実行時に実行したいメソッドはどこですか?あなたはMeCommandクラスを使用すると言っていますが、私が言及したように任意のカスタムクラスを使用したくありません。 – MegaMind

+0

すでに述べたように、コマンドシステムはWPFによって実装されており、変更することはできません。 RelayCommand/DelegateCommandなどの実装がありますが、コマンドを使用する場合は、ICommandインターフェイスを実装する必要があります。そのような単純な。 ダイレクトメソッドの実行が必要な場合は、イベントの使用を開始する可能性があります。 –

+0

あなたはちょうどあなたがあなたの質問で明確にしていないからです。いいスタイルではない。 –

1

、あなたの問題は、あなたが(XAMLをレンダリング)、その後、あなたのtestプロパティにある任意の値なしDataContextを設定し、最終的にプライベートメンバを設定InitializeComponentを呼び出すことです。あなたのCommandがもうnullではないことにUIが気づくべきです(これはPropertyで最後に見つかった値でした)?

なぜ遅延しそうのようなコマンドをインスタンス化しませ:それは、すぐにこれは必須ですようがあるだろうと(あなたが実行時に、後でそのコマンドを変更しない限り)あなたが変更通知を必要としない

public ICommand test 
{ 
    get 
    { 
     if(testCommand== null) 
     { 
     testCommand= new MeCommand(processor); 
     } 
     return testCommand; 
    } 
} 

その方法。ところで

は、あなたは何のコードは、コマンドバインディングのシナリオで実行されていない感を得るいくつかのスポットがあります:

1)がCanExecute()がfalseを返す:ちょうどあなたのビジネスのケースに応じてtrueを返すかを評価。

2)CanExecuteの条件はtrueを返しますが、呼び出されません。コマンドをCommandManagerクラスにフックすることができます。hereを参照してください。これを試す前に1)が解決されていることを確認してください。これにより、UIがCanExecuteをかなり頻繁に再クエリすることが保証されます。まだ十分でない場合は、メソッドCommandManager.InvalidateRequerySuggested()を明示的に呼び出します。

3)バインドが間違っています。そのような結合コードを変更します。

Command="{Binding Path=test, PresentationTraceSources.TraceLevel=High}" 

バインディングの値が引っ張られたり押された時はいつでもこれはあなたの出力ウィンドウをスパムします。 「最終値を使用する」という用語を探します。それがヌルなら、あなたのコマンドはどこにあるのか(まだ)ではありません。

+0

私の拘束力は問題ありません。 ICommandを別のクラスに実装せずにコマンドをバインドし、そのクラスを使用する方法を知りたいだけです。私の場合、MeCommand。 – MegaMind

+2

CommandBindingはICommandの実装でのみ機能します。それはWPF Conventionであり、助けられません。おそらくRelayCommandのようなものを使うことを考えたいと思うかもしれません。[here](http://msdn.microsoft.com/en-us/magazine/dd419663.aspx)見てみな。 –

+2

正直、なぜ私たちのすべてをdownvote?これがコミュニティに役立つと思いますか? –

2

新しいクラスを作成したくない場合は、routedコマンドを使用してください。ここに小さなスニペットがあります。私は保存としてルーティングされたコマンドを作成して、ウィンドウのコマンドバインディングbutton.and出来上がりからコマンドを上げるためにそれをバインドしています!.....私はこれがあなたに

public partial class Window1 : Window 
{ 
    public static readonly RoutedCommand Foo = new RoutedCommand(); 

    public Window1() 
    { 
     InitializeComponent(); 
    } 

    void Foo_CanExecute(object sender, CanExecuteRoutedEventArgs e) 
    { 
     // The Window gets to determine if the Foo 
     // command can execute at this time. 
     e.CanExecute = true; 
    } 

    void Foo_Executed(object sender, ExecutedRoutedEventArgs e) 
    { 
     // The Window executes the command logic when the user wants to Foo. 
     MessageBox.Show("The Window is Fooing..."); 
    } 
} 

<Window.CommandBindings> 
<CommandBinding 
    Command="{x:Static local:Window1.Foo}" 
    CanExecute="Foo_CanExecute" 
    Executed="Foo_Executed" 
    /> 

私を助けることを願ってあなたの問題をよく理解してくれることを願って

PS:コマンドの設計パターンの必要性は、コマンドの実行と呼び出しのロジックを切り離すことです。コマンドクラスは、ロジックをカプセル化する方法です。

3

RelayCommandが組み込まれているMVVMのライトフレームワークを使用する傾向があります。

あなたはそれにrelaycommandを割り当て、あなたのビューモデルにICommandのプロパティを追加します - あなただけの正常な結合を使用してXAMLで

ICommand ClickMeCommand {get;set;} 
private void InitCommands() 
{ 
    ClickMeCommand = new RelayCommand(()=>HasBeenClicked=true); 
    //or 
    ClickMeCommand = new RelayCommand(ClickMeEvent); 
} 
public void ClickMeEvent() 
{ 
    HasBeenClicked=true; 
} 

: - WPFウィンドウで

<Button Content='Push me' Command='{Binding ClickMeCommand}' /> 
0

をキーボードショートカットをリンクするには、デリゲートでバインディングを追加し、それをキージェスチャに関連付けます。

public YourWindow() //your constructor 
{ 
    ... 
    //bind keyboard command shortcuts 
    InputBindings.Add(new KeyBinding(//add a new key-binding, bind it to your command object which takes a delegate 
     new WindowCommand(this) 
     { 
     ExecuteDelegate = TogglePause //REPLACE TogglePause with your method delegate 
     }, new KeyGesture(Key.P, ModifierKeys.Control))); 
    ... 
} 

それに設定された任意の方法をオフに解雇した実行デリゲートを取る簡単なWindowCommandクラスを作成します。

public class WindowCommand : ICommand 
{ 
    private MainWindow _window; 
    public Action ExecuteDelegate { get; set; } 

    public WindowCommand(MainWindow window) 
    { 
     _window = window; 
    } 

    public bool CanExecute(object parameter) 
    { 
     return true; 
    } 

    public event EventHandler CanExecuteChanged; 

    public void Execute(object parameter) 
    { 
     if (ExecuteDelegate != null) 
     { 
      ExecuteDelegate(); 
     } 
     else 
     { 
      throw new InvalidOperationException(); 
     } 
    } 
} 
関連する問題