Search code examples
wpfmvvmlistboxcommanddatatemplate

WPF MVVM: How to enable/disable buttons in ListBox if I'm using a DataTemplate


I have a WPF/MVVM app with a ListBox which displays data through a DataTemplate. I managed to change the selected item in the ListBox when pressing a button so the CommandParameter is linked to the ListBox's SelectedItem, but I cannot get the buttons to be enabled/disabled correctly in the same way. For example, if I have 2 items and the button should be enabled in one and disabled in the other, when I select an element BOTH buttons have the same state, and they BOTH change state when I select another item.

I am using a RelayCommand as used in many MVVM Frameworks.

Here is my XAML (removed "not interesting" parts):

<UserControl.Resources>

    <DataTemplate x:Key="ItemTemplate">
            <Grid>
                <Button Content="Something" Name="EnabledDisabledButton" Click="Button_Click"
                            Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type UserControl}}, Path=DataContext.SomeCommand}"
                            CommandParameter="{Binding RelativeSource={RelativeSource AncestorType={x:Type ListBox}}, Path=SelectedItem}"/>
            </Grid>
    </DataTemplate>


    <Style TargetType="{x:Type ListBoxItem}" x:Key="ContainerStyle">
        <Setter Property="ContentTemplate" Value="{StaticResource ItemTemplate}" />
    </Style>

</UserControl.Resources>

   <ListBox x:Name="myListBox" ItemsSource="{Binding ElementList}"
             IsSynchronizedWithCurrentItem="True" ItemContainerStyle="{StaticResource ContainerStyle}"/>

I tried to pass the SelectedItem as a parameter to the RelayCommand's CanExecute method, but the result was the same as before.

Is there a way to pass the actual ListBoxItem in which the button "lives in" as a parameter to the command, so each one will be processed separately by the CanExecute method? Would it work if I got this? (right now I am handling the Click event to select the correct item in the list before executing the command).

In my CanExecute method I am evaluating some property of the SelectedItem in order to enable/disable the corresponding button. An alternative would be to evaluate this property for all elements, but I cannot think of a way to do it inside the ViewModel, and then communicate to the view the result (if it is even possible while using a DataTemplate for the items).

Thanks for your input, regards!


Solution

  • Converting My comment into an answer:

    Why not just CommandParameter="{Binding}"?