Trying to understand list selection in MvvM pattern with ICommands (no specific framework)

85 views Asked by At

First note that I am not referring to any specific framework or technology like XAML. The question is how to implement the MvvM pattern using ICommand for selection of an item in a list (=clicking a row)?

I have a view model (pseudo code):

class ListViewModel
{
// Items in the list.
public ObservableCollection<T> Items {};

// Command for item selection.
public ICommand ItemSelectedCommand
{
...
}

// Select an item in the list.
public void SelectItem(int index)
{
...
}

// The current selected item.
public T SelectedItem
{
 get { ... };
}
}

How would I now connect my UI to that view model "manually"? Say, for instance in an iOS application. I would probably have a UITableViewController, get an instance of the view model and populate the UITableView contents from it. Then I would trigger the ICommand from the RowSelected() method. And here comes the thing I don't understand: how does the view model now know which item index was selected? I don't want to call SelectItem() because then I would not need the loosely coupled ICommand at all. And maybe here we have to look how it is solved in XAML to understand the trick?

1

There are 1 answers

1
Marc On BEST ANSWER

Coming from XAML and WPF, there are two options to forward selection changes from the UI to the ViewModel (as I understand your question, you're not asking about the other way around - feedbacking changes in the ViewModel to the UI - here):

Command with payload

The ICommands Execute method has a payload parameter. Executing a command without a payload can be done passing null:

SomeCommand.Execute(null);

In your case, it would make sense to pass the selected item as the parameter in the event handler:

vm.ItemSelectedCommand.Execute(eventArgs.SelectedItem);

or

vm.ItemSelectedCommand.Execute(myList.SelectedItem);

In the command's execution method, you can handle the parameter. Note that your ViewModel property SelectedItem is not directly involved here. If you need the selected index explicitly (which is not the case, usually), I would check the selected item's index in the Items collection.

Binding selected item of list to a ViewModel property

Option B is to 'bind' the selected item of the list to a distinct property on the ViewModel, in your case the SelectedItem property in the event handler of the list:

vm.SelectedItem = myList.SelectedItem;

The command is kind of redundant then, although you could invoke it without a payload after setting SelectedItem on the ViewModel. I would rather handle the change of the selected item in the set accessor of the property on the ViewModel.

Note: XAML and WPF come with quite a lot of infrastructure code out of the box. MVVM doesn't make sense without a proper framework to actually take care of binding UI and ViewModels in a loosely coupled way. You quickly end up with a lot of extra work and little benefit, because you're still maintaining tight dependencies. Bottom line: I recommend getting or writing a proper MVVM framework, before actually implementing it.