鉴于以下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
。
再次感谢。
答案 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,同时提供相同的DataContext
。 Button
根本不需要引用ComboBox
。
<ComboBox
DisplayMemberPath="Name"
ItemsSource="{Binding Path=Advisories}"
SelectedItem="{Binding Path=SelectedAdvisory}" />
<Button Command="{Binding Path=AddAdvisoryCommand}"
CommandParameter="{Binding SelectedAdvisory}"
Content="Add..." />