2009-08-15 9 views
6

バインディングで使用したいRoutedUICommandを含む静的クラスがあります。コードビハインドにないRoutedUICommandへのバインド

public static class CommandLibrary 
{ 
    public static ProjectViewModel Project { get; set; } 

    public static RoutedUICommand AddPage { get; private set; } 

    static CommandLibrary() 
    { 
     AddPage = new RoutedUICommand("AddPage", "AddPage", typeof(CommandLibrary)); 

    } 

    public static void AddPage_Executed(object sender, ExecutedRoutedEventArgs args) 
    { 
     Project.AddPage(); 
    } 

    public static void AddPage_CanExecute(object sender, CanExecuteRoutedEventArgs args) 
    { 
     // We need a project before we can add pages. 
     if (Project != null) 
     { 
      args.CanExecute = true; 
     } 
     else 
     { 
      // Did not find project, turning Add Page off. 
      args.CanExecute = false; 
     } 
    } 
} 

私はこれのaddPageコマンドにいるCommandBindingを作成しようとすると、VSは...すべての例は、私が見てきたことを考えれば意味がありません、それはウィンドウ1でAddPage_CanExecuteを見つけることができないことを訴えて、かんしゃくをスローします私もMenu.CommandBindingsセクションを含めて、単に(this questionごとに、このことを示唆しているが、特定されていない)、これを使用していない試した

<Window x:Class="MyProject.Window1" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:local="clr-namespace:MyProject"> 
    <Menu> 
     <Menu.CommandBindings> 
      <CommandBinding Command="local:CommandLibrary.AddPage" 
          Executed="AddPage_Executed" CanExecute="AddPage_CanExecute" /> 
     </Menu.CommandBindings> 
     <MenuItem Header="_Page"> 
      <MenuItem Header="_New" Command="local:CommandLibrary.AddPage" /> 
     </MenuItem> 
    </Menu> 
</Window> 

:このXAMLは、私が場所で持っているコードを考慮し問題ないはず示します。

<MenuItem Header="_New" Command="{x:Static local:CommandLibrary.AddPage}" /> 

これはエラーの流れを開始しましたが、生成するメニュー項目は常に無効になっています。 CanExecuteは決して呼び出されないようです。私はバインディングがこの場合も失敗していると想定していますが、もっと静かにはなりますが。

はなぜVSは私のコマンドを嫌い、実行されるとCanExecute方法を見つけるために、適切な場所で見て拒否するのでしょうか?私はそれをやっているとして、これを行っていること(オンラインマシューマクドナルドにより、いくつかのカスタムコマンドのチュートリアルにプロWPFで)多くの例を見てきました。

答えて

11

A CommandBindingは自分のビジュアルツリー内の他の要素と同様です。指定されたイベントは、ビジュアルツリーのルート(この場合はWindow)によって処理されます。つまり、AddPage_ExecutedAddPage_CanExecuteをあなたのウィンドウのコードに移動すると、それが機能します。これにより、多くのUIコンポーネントで同じコマンドを使用できますが、ハンドラは異なります。

しかし、あなたのコマンドは、あなたのビューモデルに対していくつかのロジックを実行することがわかります。時間と欲求不満を解消するために、ここではルーティングされたコマンドが間違った解決策であることを理解しています。代わりに、あなたのビューモデルでは、このような何かあなたのコマンドをカプセル化:

public class ProjectViewModel 
{ 
    private readonly ICollection<PageViewModel> _pages; 
    private readonly ICommand _addPageCommand; 

    public ProjectViewModel() 
    { 
     _pages = new ObservableCollection<PageViewModel>(); 
     _addPageCommand = new DelegateCommand(AddPage); 
    } 

    public ICommand AddPageCommand 
    { 
     get { return _addPageCommand; } 
    } 

    private void AddPage(object state) 
    { 
     _pages.Add(new PageViewModel()); 
    } 
} 

DelegateCommandしてコマンドを実行し、照会するデリゲートを呼び出すICommandの実装です。つまり、コマンドロジックがすべてコマンドにラップされ、ハンドラを提供するためにCommandBindingは必要ありません(CommandBindingはまったく必要ありません)。

+0

偉大な答え。私が必要としていたものを私に与えました。私はいくつかのMVVMチュートリアルを読んでいましたが、このようなコマンドの使用を以前から見ていましたが、それを行う方法を覚えていないので、私の書籍や検索で見つけたソリューションに頼りました。ご協力いただきありがとうございます。 – evizaer

+0

Beautifull。私はこの1つに私の頭を叩いていた...学習wpf + mvvmは、私が望むようにまっすぐ進むわけではありません。 RoutedUICommands私が意図したものにはあまりにも複雑で、簡単な方法があるはずです。 @ケント、あなたの例とブログをありがとう。 –

関連する問題