0

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 :-)

tom2051
  • 82
  • 9
  • Can you please show your code (the VM - viewmodel), that will help. Also why not just do the binding for `IsChecked` just like you did for `Command`. It could be `IsChecked = "{Binding PropName}"`... If you want to pass a parameter, look at the `CommandParameter` property, [*here*](https://stackoverflow.com/a/20275938/1797425) is an example. – Trevor Aug 06 '20 at 15:02

2 Answers2

0

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.

Andy
  • 11,864
  • 2
  • 17
  • 20
  • Thanks for your answer. I did the function call in the isChecked-event in the MyView.xaml.cs before, which worked fine, but I wanted to seperate the view from the code, thats why I started using a command, which caused the problem of the command not knowing which of the checkboxes was set. Still I am interested in how to get a object or string from the view to the command. That topic often hit me before. – tom2051 Aug 07 '20 at 16:26
0

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.

mm8
  • 163,881
  • 10
  • 57
  • 88
  • Thanks a lot, this solves my problem. I dont need a command, just call my function when set of the binded property is called. The easiest solution is always best one :-) But still I would really be interested in a way to give a object or string to a binded command ... – tom2051 Aug 07 '20 at 16:18