ComboBox,Button& ICommand绑定(MVVM-ish)

时间:2012-02-09 13:15:02

标签: wpf binding icommand

鉴于以下XAML ......

<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,Button和Command的方法,当ComboBox的值发生更改时,会在Command上调用CanExecute。我想要的净效果是能够根据列表中选择的项目来启用和禁用Button,我更喜欢使用ICommand接口来执行此操作。

我过去通过使用VM上的“SelectedAdvisory”属性并在命令对象上手动调用RaiseCanExecuteChanged(我使用的是PRISM v4中的DelegateCommand实例)来完成此操作,但我确信有更好更清洁仅使用XAML执行此操作的方法。

感谢。

编辑:此外,是否有更简单的方法从Button引用ComboBox?我尝试使用RelativeSource PreviousData但无法使其工作,因此使用x:Name

再次感谢。

2 个答案:

答案 0 :(得分: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 
}

代码是手写的,因此可能存在一些错误。

答案 1 :(得分:1)

你现在设置的是我会做的。如果命令可以执行或不执行是业务规则,这意味着它应该从ViewModel处理,而不是View

唯一的区别是,我提出的是提升ViewModel的CanExecuteChanged()事件中的PropertyChange,而不是set <{1}}

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

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

如果可能的话,我更喜欢将逻辑从我的getter / setter中删除,并且使用PropertyChanged事件可以让我看到属性在一个位置发生变化时发生的所有事情。

当然,如果您使用的是RelayCommand而不是DelegateCommand,那么当属性发生变化时,您无需手动提升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..." />