I have a checkbox list of sports which is bound to an observable collection using the MVVM pattern. The user can select any number of sports he\she enjoys and when the OK button is pressed the selected sports must be displayed in the message box(simplified the code for the sake of the question).
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?
I cannot use <Button IsEnabled="{Binding ElementName=checkBox1, Path=IsChecked}" /> because there are multiple properties in the dev code which need to be checked for validity before the button can be used and because I'm using Prism, so this should be achieved using the IsValid method if at all possible.
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>
View Model
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;}
}
}
}