wpf CheckBox command parameter

1.3k Views Asked by At

In my View I have 8 checkboxes all bound to a different property in the Model, lets say bool port1 ... port8. The property changes when the concerned checkbox is clicked. When the user checks or unchecks one of these checkboxes, I also execute a binded command 'SetPortCommand'. The command executes a function like SetPort(uint numPort, bool set) My view looks like this:

<CheckBox x:Name="cbPort1" Content="port1" Command="{Binding SetPortCommand}">
    <CheckBox.IsChecked>
        <Binding Path="MyModel.Port1"/>
    </CheckBox.IsChecked>
</CheckBox>

Behind the whole thing is quite slow hardware, so I would like to avoid calling the function SetPort() for each port. I could use 8 commands like SetPortCommand1 to SetPortCommand8, but that causes lots of duplicate code. I had the following ideas, but I do not know how to implement it, neither which one wouldf be conform to MVVM.

  1. idea would be to somehow pass a constant to the command, telling it which of the 8 ports it should check or uncheck. Is there a easy way to do this?
  2. idea would be to somehow use the OnPropertyChanged()-Event to call the function in here.

Any help appreciated :-)

2

There are 2 best solutions below

1
mm8 On BEST ANSWER

You could avoid exeucting the command and just call your method from each setter, e.g.:

private bool _port1;
public bool Port1
{
    get { return _port1; }
    set { _port1 = value; SetPort(); }
}

If the SetPort modifies the other properties, you could use a flag to determine whether it should be invoked:

private bool _setPort = true;

private bool _port1;
public bool Port1
{
    get { return _port1; }
    set
    { 
        _port1 = value;
        if (_setPort)
        {
            _setPort = false;
             SetPort(); 
            _setPort = true;
        }
    }
}

You could do the same thing in the Execute method of your command if you still want to use a command for some reason.

The _setPort field prevents the method from getting called for each source property.

Alternatively, you could also avoid setting the property in the method and instead set the backing field and raise the PropertyChanged event: _port2 = true; OnPropertyChanged(nameof(Port2));

This will bypass the setter and avoid calling the method.

1
Andy On

With a checkbox, the usual approach is to bind ischecked and to act in that setter. This uses text rather than a bool, but you can see there's a method called in the setter. https://social.technet.microsoft.com/wiki/contents/articles/30564.wpf-uneventful-mvvm.aspx#Change_of_Variable

You have a repeating group of functionality in this set of check boxes.

The usual approach is to bind a list or observablecollection of viewmodels to the itemssource of an itemscontrol. Template that data out into your ui. Here you'd have checkboxes. Each of your row viewmodels would hold data about a port. Name and whatnot.

If you particularly want a command you could have an ICommand such as delegatecommand or relaycommand bound from either:

The row viewmodel - in which case that "knows" which port is to be acted on. And your code that does stuff with that port is in the row viewmodel.

or

To the window viewmodel, in which case the row viewmodel is the datacontext of the button and this is passed as a parameter to the ICommand.

Both these are common scenarios working with buttons and you should be able to find code googling.

Binding IsChecked would be simpler and is hence more usual though.