0

I am writing a WPF app using the MVVM pattern and I am having the following problem: I have bound a command to a checkbox in my UI however my event handler is not being called when the check box is clicked. I have used the same approach to bind other UI elements such as buttons and it seems to work alright for them. The relevant xaml is as follows:

<ListBox ItemsSource="{Binding ElementsMethods}" Height="auto" x:Name="MethodsListBox">
                                        <ListBox.ItemTemplate>
                                            <DataTemplate>
                                                <StackPanel Orientation="Horizontal">
                                                    <TextBlock Text="{Binding FormattedEM}"/>
                                                    <StackPanel Orientation="Horizontal">
                                                        <TextBlock Text="Started"/>
                                                        <Checkbox IsChecked="{Binding Started} Command="{Binding elementMethodCheckboxChangeCommand}"> </CheckBox>
                                                    </StackPanel>
                                                    <StackPanel Orientation="Horizontal">
                                                        <TextBlock Text="Finished"/>
                                                        <CheckBox IsChecked="{Binding Finished}"></CheckBox>
                                                    </StackPanel>
                                                </StackPanel>
                                            </DataTemplate>
                                        </ListBox.ItemTemplate>IsChecked="{Binding Finished}

Where elementMethodCheckboxChangeCommand is a public property of type ICommand in my viewmodel class:

public ICommand elementMethodCheckboxChangeCommand { get; set; }

the concrete class used to set this property is named relay command:

elementMethodCheckboxChangeCommand = new RelayCommand(new Action<object>(elementMethodCheckboxChange));

where elementMethodCheckboxChange is a public void function taking a parameter of type object. The implementation of the relaycommand class is as follows:

class RelayCommand : ICommand
{
    private Action<object> _action;
    public RelayCommand(Action<object> action)
    {
        _action = action;
    }
    public bool CanExecute(object parameter)
    {
        return true;
    }
    public void Execute(object parameter)
    {
        if (parameter != null)
        {
            _action(parameter);
        }
        else
        {
            _action("Hello world");
        }
    }
    public event EventHandler CanExecuteChanged;
}

Like I said above I have used this same approach to bind to buttons in my UI and they have worked as expected, however when I click the checkbox nothing happens at all, and my event handler is not executed.

I hope someone can help me out here as this problem is starting to become really frustrating - please ask if you need any additional information. Thank you all in advance :)

  • Check output window for binding errors. Your command is in view model and to bind like you do it has to be located inside each `ElementsMethods` item (whatever it is, you didn't show). As a fix you need to use relative source to find parent (e.g. window, or listbox) and use `Path = DataContext.elementMethodCheckboxChangeCommand` to bind. See [this answer](https://stackoverflow.com/a/5830152/1997232). – Sinatr Sep 17 '20 at 14:28
  • Does this answer your question? [binding a command inside a listbox item to a property on the viewmodel parent](https://stackoverflow.com/questions/5063308/binding-a-command-inside-a-listbox-item-to-a-property-on-the-viewmodel-parent) – Sinatr Sep 17 '20 at 14:31
  • Thank you for your informative answer - changing the command to be a static property in my ElementMethodsPair class seems to have done the trick (Although it seems to me like logically all commands would be best of located in the viewmodel class). I Will digest the rest of your comment and read up more about what you have said with regards to relative source - thank you once again – Jim Marshall Sep 17 '20 at 14:41

1 Answers1

0

You should specify a RelativeSource of the binding when you want to bind to a property of the view model inside an `ItemTemplate:

<CheckBox ... Command="{Binding DataContext.elementMethodCheckboxChangeCommand,
            RelativeSource={RelativeSource AncestorType=ListBox}}"/>

The default DataContext is the current item in the ItemsSource and this one has no elementMethodCheckboxChangeCommand property to bind to.

Making the property static is not a very good solution.

mm8
  • 163,881
  • 10
  • 57
  • 88