Haacker
Haacker

Reputation: 21

Enabling Button in ListBox only when its item is selected

I am using MVVM Light, and I have a listbox with a data template so that each row of the listbox displays an "Edit" button and a name.

I am able to connect the button to the ViewModel with EventToCommand and a RelayCommand object.

I am also able to disable the button control until an item in the listbox is selected with a data trigger on the button. Here is that xaml:

<DataTrigger
    Binding="{Binding ElementName=lbPlayersList, Path=SelectedItem}"
    Value="{x:Null}">
    <Setter Property="Button.IsEnabled" Value="False"/>
</DataTrigger>

Here is my issue. When an item is selected, ALL of the buttons are enabled. so if you select item 1 in the list, all buttons are enabled, which means that you might then click on the button on item 2, while item 1 is selected, and then the person in item 1 is passed as the CommandParameter instead of the person on item 2.

What I would like to know is if there is a way to do either of the following:

  1. leave ALL of the Edit buttons enabled, and when the user clicks on one, then the row that it belongs to becomes the SelectedItem of the listbox, ensuring that the expected person item is passed as the CommandParameter when the button is clicked
  2. disable all of the Edit buttons, and when a person in the listbox is selected, only the edit button for that row of the listbox is enabled, again, ensuring that the desired user is passed as the CommandParameter for the command.

Thanks, Steve

UPDATE: What about something like this (it's not working, but I'm probably just doing something wrong).

<DataTemplate x:Key="PlayersListTemplate">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="auto"/>
            <ColumnDefinition Width="auto"/>
        </Grid.ColumnDefinitions>
        <Button Grid.Column="0" IsEnabled="False" Content="Edit" Margin="4,4,8,4" Height="25" Width="25" FontSize="10" VerticalAlignment="Center">
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="Click">
                    <GalaSoft_MvvmLight_Command:EventToCommand x:Name="EditButtonClick" 
                                                                Command="{Binding Source={StaticResource Locator}, Path=Main.TestCommand}"
                                                                CommandParameter="{Binding ElementName=lbPlayersList, Path=SelectedItem}"/>
                </i:EventTrigger>
            </i:Interaction.Triggers>
            <Button.Style>
                <Style>
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type ListBoxItem}},Path=IsSelected}" Value="True">
                            <Setter Property="Button.IsEnabled" Value="True"/>
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </Button.Style>
        </Button>
        <StackPanel Grid.Column="1" VerticalAlignment="Center">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="auto"/>
                    <RowDefinition Height="auto"/>
                </Grid.RowDefinitions>
                <StackPanel Orientation="Horizontal" Grid.Row="0">
                    <TextBlock Text="{Binding LastName}" FontSize="16" FontWeight="DemiBold" />
                    <TextBlock Text=", " FontSize="16" FontWeight="DemiBold"  VerticalAlignment="Center"/>
                    <TextBlock Text="{Binding FirstName}" FontSize="16" FontWeight="DemiBold" VerticalAlignment="Center"/>
                </StackPanel>
                <TextBlock Text="{Binding NickName}" Grid.Row="1" FontSize="10" />
            </Grid>
        </StackPanel>
    </Grid>
</DataTemplate>

The part I am talking about is on the Button.Style where I would try to check if its ancestor (the listboxitem that it belongs to) is selected, and if so, then enable that button. However, the button is not being enabled when the item is selected.

Upvotes: 2

Views: 3536

Answers (1)

AxelEckenberger
AxelEckenberger

Reputation: 16926

Possibly the easiest way is to implment an IsSelected property in you PersonViewModel and bind that to the IsSelected of your ListBoxItem with a two-way binding. Now you can pass the person to your command via the CommandParameter (CommandParameter="{Binding}").

Once this infrastructure is in place you now can use your command's CanExecute method - accepts the CommandParamter as input - to determine whether the person is selected and your command should, therefore, be enabled (solution for point 2 in your 'wish list').

For point 1 in your 'wish list' the implementation is even easier:

new RelayCommand(
    (p) => { /* execution method, p holds the command parameter */ }
    (p) => { /* can execute method, p holds the command parameter */ }
);

Binding:

<Button Content="Edit" 
        Command="{Binding DataContext.EditCommand, RelativeSource={RelativeSource AncestorType=ListBox}}" 
        CommandParameter="{Binding}"

Upvotes: 1

Related Questions