2012-02-09 20 views
3

...コンボボックス、ボタン&ICommandのバインディング(MVVMっぽい)

<ComboBox x:Name="advisoriesComboBox" 
    DisplayMemberPath="Name" 
    ItemsSource="{Binding Path=Advisories}" 
    SelectedItem="{Binding Path=SelectedAdvisory}" /> 

<Button Command="{Binding Path=AddAdvisoryCommand}" 
    CommandParameter="{Binding ElementName=advisoriesComboBox, Path=SelectedItem}" 
    CommandTarget="{Binding ElementName=advisoriesComboBox}" 
    Content="Add..." /> 

私はそれがとき値ようにコンボボックス、ボタンとコマンドをバインドする方法を探していますComboBoxが変更されると、CanExecuteがCommandで呼び出されます。私が望むことの正味の効果は、リスト内で選択されている項目に基づいてボタンを有効または無効にすることができるようにすることです。ICommandインターフェイスを使用してこれを行うことをお勧めします。

これは、VMで "SelectedAdvisory"プロパティを使用し、コマンドオブジェクトでRaiseCanExecuteChanged(PRISM v4のDelegateCommandインスタンスを使用しています)を手動で呼び出すことでこれまで行ってきましたが、 XAMLのみを使用してこれを行うためのよりクリーンな方法です。

ありがとうございました。

EDIT:さらに、ボタンからComboBoxを参照する簡単な方法はありますか?私はRelativeSource PreviousDataを使ってみましたが、動作させることができませんでしたので、使用法x:Name

もう一度おねがいします。

+0

あなたが過去にしたことは、私にはかなりいいようです。私はXAMLがこのようなもののために良い場所であるかどうかはわかりません。 – ken2k

答えて

1

あなたが今セットアップしていることは、私がやることです。コマンドが実行可能かどうかをビジネスルールとすると、ではなく、ViewModelから処理する必要があります。

唯一の違いは、私が代わりにSelectedAdvisory

void MyViewModel() 
{ 
    this.PropertyChanged += MyViewModel_PropertyChanged; 
} 

void MyViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e) 
{ 
    switch(e.PropertyName) 
    { 
     case "SelectedAdvisory": 
      ((DelegateCommand)AddAdvisoryCommand).RaiseCanExecuteChanged(); 
      break; 
    } 
} 

set方法で、私は可能であれば私のゲッター/セッターの外にロジックを維持することを好む、あなたのViewModelのPropertyChangeイベントでCanExecuteChanged()を高めることであることを確認ですPropertyChangedイベントを使用すると、プロパティが1つの場所で変更されたときに起こるすべてを見ることができます。

もちろん、DelegateCommandの代わりにRelayCommandを使用している場合、プロパティが自動的に変更されるので、CanExecuteChanged()を手動で上げる必要はありません。

XAMLをシンプルにすると、同じものを共有することもできます。DataContextButtonは、ComboBoxをまったく参照する必要はありません。

<ComboBox 
    DisplayMemberPath="Name" 
    ItemsSource="{Binding Path=Advisories}" 
    SelectedItem="{Binding Path=SelectedAdvisory}" /> 

<Button Command="{Binding Path=AddAdvisoryCommand}" 
    CommandParameter="{Binding SelectedAdvisory}" 
    Content="Add..." /> 
+0

INotifyPropertyChangedは私が今扱う方法です。唯一の違いは、選択的に再クエリーするのではなく、すべてのプロパティの変更に対してCanExecuteを再クエリーするためにすべてのコマンドオブジェクトが必要であるということです。ありがとう。 –

+1

私は同意します。 "ショートカット"を望むなら、 'RelayCommand'は素晴らしい' ICommand'実装です。代わりに 'DelegateCommand'が好きです。' RelayCommand'は、 'CommandManager.RequerySuggested'イベントと関連しているので、あまりにも頻繁に実行されます。これにより、デバッグが面倒になります。 –

2

私はのviewmodelにすべてをするだろう、それはユニットテストに来るとき

<ComboBox x:Name="advisoriesComboBox" 
    DisplayMemberPath="Name" 
    ItemsSource="{Binding Path=Advisories}" 
    SelectedItem="{Binding Path=SelectedAdvisory}" /> 

<Button Command="{Binding Path=AddAdvisoryCommand}" 
    Content="Add..." /> 

VM

private bool CanAddExecute() 
{ 
    return this.SelectedAdvisory != null; 
} 

private void AddExecute() 
{ 
    if(!CanAddExecute()) 
     return; 

    //do here what you want, your information for the selected item is in this.SelectedAdvisory 
} 

コードは手書きなので、いくつかがあるかもしれない最高の私には思えますエラー。

+0

これはうまくいきますが、私はコマンドハンドラがオブジェクトを渡すというアイデアのようなものです(レイチェルの提案通り)。ありがとう。 –

関連する問題