14

複雑な方法を何度も使いすぎて、タスクを実行する最も簡単な方法を忘れてしまうこともありました。

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

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();
    }
}

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

4

6 に答える 6

16

Prismは既にMicrosoft.Practices.Prism.Commands.DelegateCommandを提供しています

サードパーティと見なされるかどうかはわかりません。少なくとも公式であり、MSDN で文書化されています。

コピー、貼り付けなどの一部のネイティブ ビルトイン コマンドは、ICommand インターフェイスを実装します。私見は、オープン(拡張の場合)/クローズ(変更の場合)の原則に従っています。独自のコマンドを実装できるようにします。


アップデート

ここに記載されている WPF Commanding として、抜粋...

WPF には、一連の定義済みコマンドが用意されています。Cut、BrowseBack、BrowseForward、再生、停止、一時停止など。

コマンド ライブラリ クラスのコマンドがニーズを満たさない場合は、独自のコマンドを作成できます。カスタム コマンドを作成するには、2 つの方法があります。1 つ目は、ICommand インターフェイスをゼロから実装することです。もう 1 つの方法で、より一般的な方法は、 RoutedCommandまたはRoutedUICommandを作成することです。

最初に RoutedCommand モデルを試し、最終的に ICommand を実装しました。

XAML バインディングのサンプル

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

RoutedCommand は RoutedEvent と同じです。これは、より良いボタンの 'Clicked' イベント ハンドラーのようです。アプリのロジックをビューから分離するが、DependencyProperty またはコード ビハインドをアタッチする必要があります。

個人的には、ICommand を実装するだけでより快適に感じます。

于 2012-12-12T12:07:29.720 に答える
3

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

ビューモデルにICommandプロパティを追加してから、それにリレーコマンドを割り当てます。-

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

xamlでは、通常のバインディングを使用します:-

<Button Content='Push me' Command='{Binding ClickMeCommand}' />
于 2012-12-20T16:38:44.297 に答える
2

新しいクラスを作成したくない場合は、routed コマンドを使用してください。ここに小さなスニペットがあります。ルーティングされたコマンドを Save として作成し、それを window のコマンド バインディングにバインドし、button.and voila からコマンドを発生させます!..... これが役立つことを願っています。

 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: コマンド デザイン パターンの必要性は、実行のロジックとコマンドの呼び出し元を分離することです。そのため、コマンド クラスはロジックをカプセル化する方法です。

于 2012-12-20T05:38:39.160 に答える
1

VSでコードを実行せずに行うことから判断すると、問題は、呼び出しInitializeComponent(XAMLのレンダリング)を行いDataContext、プロパティに値を指定せずtestに設定し、最後にプライベートメンバーを設定することです。UIは、コマンドがnullではなくなったこと(プロパティで最後に見つかった値)をどのように認識しますか?

そのように怠惰にコマンドをインスタンス化してみませんか:

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

そうすれば、必要に応じてすぐにそこに表示され、変更通知は必要ありません(後でそのコマンドを実行時に変更しない限り)。

ちなみに、コマンドバインディングシナリオでは、コードが実行されていないと感じる場所がいくつかあります。

1)CanExecute()はfalseを返します:trueを返すか、ビジネスケースに従って評価します。

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

3)バインディングが間違っています。バインディングコードを次のように変更します。

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

これにより、バインディングの値がプルまたはプッシュされるたびに、出力ウィンドウにスパムが送信されます。「最終値を使用する」という用語に注意してください。nullの場合、コマンドは(まだ)本来あるべき場所にありません。

于 2012-12-18T12:11:06.610 に答える
0

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

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

ここまで。

別の方法として、test = new MeCOMmand(); を実行することもできます。DataContext = これ;

于 2012-12-16T09:38:28.543 に答える