我有一个使用 MVVM 模式绑定到可观察集合的运动复选框列表。用户可以选择他/她喜欢的任意数量的运动,当按下 OK 按钮时,所选运动必须显示在消息框中(为了问题而简化了代码)。
The OK button must be enabled only if one or more sports have been selected, at the moment this is not working.The enabling\disabling of the button is done using IsValid
, is there any way to execute this method everytime one of the checkboxes is checked ?
我不能使用<Button IsEnabled="{Binding ElementName=checkBox1, Path=IsChecked}" />
,因为开发代码中有多个属性需要在使用按钮之前检查其有效性,并且因为我使用的是 Prism,所以如果可能的话,应该使用该IsValid
方法来实现。
XAML
<Window x:Class="WpfApplication13.MVVM.ComboboxWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:prism="clr-namespace:Microsoft.Practices.Composite.Presentation.Commands;assembly=Microsoft.Practices.Composite.Presentation"
xmlns:local="WpfApplication13.MVVM" Title="MainWindow" Height="170" Width="507">
<Grid>
<ListBox ItemsSource="{Binding Sports}" Name="lbModules" ScrollViewer.VerticalScrollBarVisibility="Visible"
Height="72" Margin="3" VerticalAlignment="Top">
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding Text}" IsChecked="{Binding IsChecked,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Name="chkModules" Margin="0,5,0,0" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button Height="27" Width="70" Margin="3,80,3,3" VerticalAlignment="Top"
Content="OK" HorizontalAlignment="Left"
prism:Click.Command="{Binding Path=NewCommand}"></Button>
</Grid>
</Window>
查看模型
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Windows;
using Microsoft.Practices.Composite.Presentation.Commands;
namespace WpfApplication13.MVVM
{
public class MainWindowViewModel : INotifyPropertyChanged
{
public DelegateCommand<object> NewCommand { get; protected set; }
public event PropertyChangedEventHandler PropertyChanged;
private ObservableCollection<ListHelper> modules = new ObservableCollection<ListHelper>();
public ObservableCollection<ListHelper> Sports
{
get { return modules; }
set { modules = value; OnPropertyChanged("Sports"); }
}
protected virtual void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
NewCommand.RaiseCanExecuteChanged();
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public MainWindowViewModel()
{
ListHelper item1 = new ListHelper() { Text = "Footbal", IsChecked = false };
ListHelper item2 = new ListHelper() { Text = "Boxing", IsChecked = false };
ListHelper item3 = new ListHelper() { Text = "Basketball", IsChecked = false };
Sports.Add(item1);
Sports.Add(item2);
Sports.Add(item3);
NewCommand = new DelegateCommand<object>(NewTemplate, IsValid);
}
private bool IsValid(object parameter)
{
//TODO:This method must execute EVERYTIME any of the checkboxes are checked\unchecked.(currently not happening)
//The return value then determines the enabled state of the button.
return Sports.Any(e => e.IsChecked);
}
private void NewTemplate(object parameter)
{
//Display a list of selected sports
string sports = String.Empty;
Sports.Where(e => e.IsChecked).ToList().ForEach(c => sports += c.Text + " ");
MessageBox.Show(sports);
}
}
public class ListHelper
{
public String Text { get; set; }
private bool isChecked = false;
public Boolean IsChecked
{
get { return isChecked; }
//The setter is executed everytime the checkbox is checked
set {isChecked = value;}
}
}
}