Reputation: 21
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:
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
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