How to use Commands to react to a ListBox

149 Views Asked by At

I'm trying to learn Commanding and have set up a simple wpf project to use a custom command. I have a ListBox and a Button on a Window. When the ListBox has the focus and an Item is selected, I want the Button to be enabled, otherwise it should be disabled.

I define a CustomCommand in a separate CustomCommands class:

Public Shared ReceivedFocus As New RoutedCommand

and in my Window I set it up as follows:

<CommandBinding
    Command="{x:Static local:CustomCommands.ReceivedFocus}"
    CanExecute="CanActivate"
    Executed="ChangeSelection">
</CommandBinding>

and use the command for the ListBox as follows:

<ListBox
    x:Name="lstInactive">
    <i:Interaction.Triggers>
        <i:EventTrigger
            EventName="GotFocus">
            <i:InvokeCommandAction
                Command="{x:Static local:CustomCommands.ReceivedFocus}"
            </i:InvokeCommandAction>
        </i:EventTrigger>
    </i:Interaction.Triggers>
</ListBox>

and, finally, the CanActivate routine is:

Private Sub CanActivate(sender As Object, e As CanExecuteRoutedEventArgs)
        If lstInactive.SelectedIndex >= 0 Then
            e.CanExecute = True
        Else
            e.CanExecute = False
        End If
End Sub

This is not working. The major problem is that I don't understand how to relate the CanExecute value to the Button. Should I ignore the CanExecute value in the CanActivate routine and instead just set the Enabled property of the Button? If so, what is the value of the CanExecute paramter of the CanExecuteRoutedEventArgs?

A second problem is that the GotFocus event is not firing until I select an item in the ListBox a second time.

Or maybe I don't have a grasp on Commanding at all and this is not the right approach. This small project is not important in itself, it is intended to make sure I understand Commanding after reading numerous articles about it before I start to use Commands in "real" projects. Sadly, at this stage it is clear I don't.

1

There are 1 best solutions below

4
mm8 On

This is not working. The major problem is that I don't understand how to relate the CanExecute value to the Button.

Bind its Command property to the same command:

<Button Content="Button" Command="{x:Static local:CustomCommands.ReceivedFocus}" />

The Button should then be enabled or disabled based on the value that you set the CanExecute property to in your CanActivate event handler.

You probably also want to listen to the SelectionChanged event. This works as expected:

<StackPanel>
    <StackPanel.CommandBindings>
        <CommandBinding
                Command="{x:Static local:CustomCommands.ReceivedFocus}"
                CanExecute="CanActivate"
                Executed="ChangeSelection">
        </CommandBinding>
    </StackPanel.CommandBindings>

    <ListBox x:Name="lstInactive">
        <ListBoxItem>first</ListBoxItem>
        <ListBoxItem>second</ListBoxItem>
        <ListBoxItem>third</ListBoxItem>
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="SelectionChanged">
                <i:InvokeCommandAction Command="{x:Static local:CustomCommands.ReceivedFocus}">
                </i:InvokeCommandAction>
            </i:EventTrigger>
        </i:Interaction.Triggers>
    </ListBox>

    <Button Content="Button" Command="{x:Static local:CustomCommands.ReceivedFocus}" />
</StackPanel>

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void CanActivate(object sender, CanExecuteRoutedEventArgs e)
    {
        e.CanExecute = lstInactive.SelectedIndex >= 0;
    }

    private void ChangeSelection(object sender, ExecutedRoutedEventArgs e)
    {

    }
}