views:

132

answers:

2

Hi,

I have list of checkboxes on a window specifying some items to be ordered. I neeed to first disable the Order button when the windows loads and enable it after selecting/check some items(checkboxes) and vice versa. I have bind the IsChecked property of the checkbox.

Kindly Suggest.

Thanks.

Edit Import from OP comment:-

I have only one checkbox in the ItemsControl. and I have bind the ItemsControl's ItemsSource to List. that way we can show multiple checkboxes as per the items in the List.

Here is the code:

<ItemsControl ItemsSource="{Binding FavoriteItems}" Margin="80,0">
  <ItemsControl.ItemTemplate>
    <DataTemplate>
      <Grid>
        <StackPanel>
          <Grid>
            <CheckBox IsChecked="{Binding IsHouseholdSelected}" Content="{Binding SubCategoryName}" Grid.ColumnSpan="1" FontFamily="Calibri" FontWeight="Bold" />
          </Grid>
        </StackPanel>
      </Grid>
    </DataTemplate>
  </ItemsControl.ItemTemplate>
A: 

Bind a command to the button and implement the CanExecute method to check the status of the checkboxes and either enable or disable the button and use the Execute method to invoke the functionality that you want on the button.

MVVM RelayCommand

CanExecute on MSDN

EDIT: Here is some source code of how to implement a RelayCommand. The RelayCommand class can be found at the first link provided above. I'm assuming that you know how to hook up the DataContext to the ViewModel implementation.

<StackPanel>
    <CheckBox Name="MyCheckBox" Content="Some CheckBox" 
              IsChecked="{Binding MyCheckBoxChecked}"/>
    <Button Content="Click me" Command="{Binding MyCommand}"/>
</StackPanel>

public class OrderViewModel
{
    private RelayCommand MyRelayCommand;

    public OrderViewModel()
    {
        MyRelayCommand = new RelayCommand(Execute, CanExecute);
        MyCheckBoxChecked = false;
    }

    public RelayCommand MyCommand
    {
        get { return MyRelayCommand; }
    }

    public bool MyCheckBoxChecked { get; set; }

    private bool CanExecute(object o)
    {
         // Here I'm just checking the property we've bound to but you can put
         // anything in here that will return a bool, including a check of any/all
         // of the checkboxes you may need to check 
         return MyCheckBoxChecked;
    }

    private void Execute(object o)
    {
        Console.WriteLine(@"Executing ...");
    }
}
Dave White
@Dave. I have already bind a commmand to the button to perform some other function. I am using mvvm light.Kindly Suggest?Thanks
Tarun
A: 

Below is a sample code that could help you out. Basically, the key here is I had the Items in the list implicitly notify its parent ViewModel's Command object to raise the CanExecuteChanged event every time the IsChecked property changes. (Also, I'm using "DelegateCommand" here, which is just the same as "RelayCommand").

ViewModels:

    public class ViewModel : INotifyPropertyChanged
    {
        public DelegateCommand MyCommand { get; set; }

        private ObservableCollection<ItemViewModel> items = new ObservableCollection<ItemViewModel>();
        public ObservableCollection<Item> Items
        {
            get { return this.items; }
        }

        public ViewModel()
        {
            this.items.Add(new ItemViewModel(this) { IsChecked = false, Text = "Item 1" });
            this.items.Add(new ItemViewModel(this) { IsChecked = false, Text = "Item 2" });
            this.items.Add(new ItemViewModel(this) { IsChecked = false, Text = "Item 3" });

            this.MyCommand = new DelegateCommand(this.CanExecute, this.Execute);
        }

        public void Execute(object parameter)
        {
            MessageBox.Show("Executed");
        }

        public bool CanExecute(object parameter)
        {
            return (this.items.Count == this.items.Count((x) => x.IsChecked));
        }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged(string propName)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propName));
            }
        }

        #endregion
    }

    public class ItemViewModel
    {
        private ViewModel parent;
        private bool isChecked;

        public string Text { get; set; }

        public bool IsChecked 
        {
            get { return this.isChecked; }
            set
            {
                this.isChecked = value;

                if (this.parent.MyCommand != null)
                    this.parent.MyCommand.OnCanExecuteChanged(null);
            }
        }

        public Item(ViewModel parent)
        {
            this.parent = parent;
        }
    }

View:

<Window x:Class="WpfApplication2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication2"
        xmlns:sys="clr-namespace:System;assembly=mscorlib"
        Title="MainWindow" Height="350" Width="525">

    <Window.DataContext>
        <local:ViewModel/>
    </Window.DataContext>

    <DockPanel>
        <Button DockPanel.Dock="Bottom" Command="{Binding MyCommand}">Test</Button>

        <ItemsControl ItemsSource="{Binding Items}">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <CheckBox IsChecked="{Binding IsChecked}" Content="{Binding Text}"/>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </DockPanel>

</Window>
karmicpuppet