I am relatively new to WPF, so this may be trivial, but I couldn't figure this out.
Let's say I have a ListBox
and a Button
. The button is binded to a command that does something on the selected item of the list.
Example:
<ListBox Name="List" ItemsSource="{Binding Items}" />
<Button Content="Show!" Command="{Binding ShowCommand}" CommandParameter="{Binding ElementName=List, Path=SelectedItem}"/>
I want the button to be disabled if and only if no item is selected, and I ideally want to do it via the ShowCommand.CanExecute
function.
I tried checking for null parameter and it worked but if only checked once in the beginning. If I select an item the button is still disable.
I tried the suggestion here: WPF CommandParameter binding not updating but it simply didn't work... (same problem) Am I doing something wrong?
How do I make him recall canExecute
when I select an item on the list? .
You can achieve that easily using a DataTrigger
<ListBox Name="List" ItemsSource="{Binding Items}" />
<Button Content="Show!" Command="{Binding ShowCommand}" CommandParameter="{Binding ElementName=List, Path=SelectedItem}">
<Button.Style>
<Style TargetType="Button">
<Setter Property="IsEnabled" Value="True" />
<Style.Triggers>
<DataTrigger Binding="{Binding SelectedItem,ElementName=List}" Value="{x:Null}">
<Setter Property="IsEnabled" Value="False"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
Update
The reason why ou couldn't achieve that using CanExecute
is most likely because the CanExecuteChanged
event wasn't raised, to fix that you can take advantage of CommandManager.RequerySuggested
by linking this event to your command's CanExecuteChanged
event[1].
Here a basic implementation and use of an ICommand
in your case:
public class Command : ICommand
{
private readonly Action<object> _action;
public Command(Action<object> action)
{
_action = action;
}
public bool CanExecute(object parameter)
{
//the selected item of the ListBox is passed as parameter
return parameter != null;
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object parameter)
{
//the selected item of the ListBox is passed as parameter
_action(parameter);
}
}
The command defined in your VM should look something like that:
private ICommand _showCommand;
public ICommand ShowCommand => _showCommand ?? (_showCommand = new Command(ButtonClickAction));
public void ButtonClickAction(object parameter)
{
//Your action
}
You might also want to take a look at Routed Commands to avoid raising the CanExecuteChanged event yourself.