Click here to Skip to main content
15,889,335 members
Please Sign up or sign in to vote.
5.00/5 (1 vote)
Hello guys,
I'm clearly missing something within a binding of a command on a button in MVVM WPF project.
I have a DataGrid which is bound to a View Model property Paths of type ObservableCollection<folders></folders> (where Folder is just a custom type with Path and Count property)
<WpfToolkit:DataGrid ItemsSource="{Binding Paths}" IsReadOnly="True" AutoGenerateColumns="False" CanUserAddRows="False"
 <WpfToolkit:DataGrid.Columns>
    <WpfToolkit:DataGridTextColumn x:Uid="Custom:DataGridTextColumn_1" Header="Path" Binding="{Binding Path}"  />
        <WpfToolkit:DataGridTextColumn x:Uid="Custom:DataGridTextColumn_2" Header="Count" Binding="{Binding Count}" />
 </WpfToolkit:DataGrid.Columns>
</WpfToolkit:DataGrid>


The user can add items to this collection only using a button which prompts him to select a folder on the system.
<Button Command="{Binding AddMoreCommand}" Content="Add more" />

The command is executed (RelayCommand technique used):

C#
public void AddMoreFolders()
 {
  IFolderBrowserDialogService fbg = GetService<IFolderBrowserDialogService>();
     if (fbg != null)
     {
      if (DialogResult.OK == fbg.Show())
        {
          string selectedPath = fbg.SelectedPath;
          Paths.Add(new Folder { Path = selectedPath, Count = 0 });
          OnPropertyChanged("Paths");
        }
      }
 }

The thing that I would like to achieve is the following: Once at least 1 folder is added in the DataGrid the Start button should become Enabled. Following is XAML for Start button.
<Button Command="{Binding StartCommand}" />

Initially it is disabled because it's underlying CanStartProcessing method returns False.
C#
public bool CanStartProcessing()
{
    return !_processing && Paths.Count > 0;
}


The thing which I'm not able to achieve is as follows: Once a folder is added to the Paths collection from the Datagrid (and OnPropertyChanged is called, I'm expecting that the CanStartProcessing will execute, as the button's command is bound to it. But it does not. I've tried almost everything including Dispatcher.CurrentDispatcher.BeginInvoke(new Action(CommandManager.InvalidateRequerySuggested)); which tries to force the UI to invalidate it's content. Any help or suggestion is greatly appreciated.
Posted
Updated 8-Apr-11 11:42am
v2

Hi,

you can also do your logik to enable/disable the Button in the Command.

C#
private RelayCommand _StartCommand;
public RelayCommand StartCommand
      {
          get { return _StartCommand ?? (_StartCommand = new RelayCommand(() => Starting(), () => CanStartProcessing())); }
      }


The first Mehod will be called if the Command is executing. The second describes if the Command isExecutable. The Button will be automatically disabled.

The update of the CanStartProcessing can be forced with:
CommandManager.InvalidateRequerySuggested()


Hope it helps
 
Share this answer
 
v2
Comments
Ciumac Sergiu 9-Apr-11 6:28am    
This logic is already implemented, the problem is that it doesn't work as described in the question.
DrNimnull 9-Apr-11 6:45am    
ohh sorry was a little remiss that i saw it too late, that you have already done these things. Can you post your Code of your RelayCommand.
Ciumac Sergiu 9-Apr-11 6:47am    
Thank you DrNimnull, I've figured out the problem, it was a simple miss within the RelayCommand class. Please see my solution below.
Thank you all for suggestions, I've figured out what was the problem. There was a need to add in the RelayCommand class the following code for CanExecuteChanged event:
C#
public event EventHandler CanExecuteChanged
{
     add { CommandManager.RequerySuggested += value; }
     remove { CommandManager.RequerySuggested -= value; }
}


Initially it was:
public event EventHandler CanExecuteChanged;

As MSDN states RequerySuggested occurs when the CommandManager detects conditions that might change the ability of a command to execute.
MVVM can be very annoying sometimes.
Regards
 
Share this answer
 
Hi Ciumac!

It doesn't look like your Start button Enabled property is bound to anything. I would make the following changes:

1. Convert your CanStartProcessing method to a Property.

C#
public bool CanStartProcessing
{
    get { return !_processing && Paths.Count > 0; }
}


2. Bind the Start button to that property.
XML
<Button Command="{Binding StartCommand}" IsEnabled="{Binding CanStartProcessing}" />


3. Raise the PropertyChanged event for your CanStartProcessing property in addition to raising it for the Paths property.
C#
if (DialogResult.OK == fbg.Show())
        {
          string selectedPath = fbg.SelectedPath;
          Paths.Add(new Folder { Path = selectedPath, Count = 0 });
          OnPropertyChanged("Paths");
          OnPropertyChanged("CanStartProcessing");
        }


Note that you will also need to raise PropertyChanged when the _processing flag changes, so that the button becomes disabled during processing.
 
Share this answer
 
v2

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900