2

This question relates to design help. In it I present a problem, and some solutions I thought of, together with my opinions of the solutions; and finally a solution I think is the correct one. I am seeking validation or challenges to my solutions. Sorry for the long post.

I have a ConfigActivityGroup class (model). It represents a group of activities. A user can have many ActivityGroups, each containing a name for the group and multiple activities which are strings.

I have a ConfigActivityGroupVM which provides Commands for CRUD on ConfigActivityGroups

The ConfigActivityGroupVM keeps an ObservableList<ConfigActivityGroup> for the ConfigActivityGroups. The ConfigActivityGroupVM also keeps a CollectionViewSource for the ObservableList<ConfigActivityGroup> and presents an ICollectionView for the UI to access.

I haven't done the UI yet, but I planned on having the ICollectionViewSource bound to a list, from which the user can click an item; and see a text box with the GroupName, and another list with the Activities for the ActivityGroup adjacent to the first list.

This is all good, as I have a concept of a current ConfigActivityGroup provided by the ICollectionView. I can use the current ConfigActivityGroup to bind to the second UI list to show the Activities in the current ConfigActivityGroup.

Problem: When I want to build Commands for CRUD on the activities of the current ConfigActivityGroup.

If the Activities in the ConfigActivityGroup are in a List<string> and I bind them directly to the UI then I have no concept of a "current" activity to which I can bind-to in the UI so that I could have a DeleteCurrentActivityCommand command in the VM delete the current activity for the current command.

First Solution I had was to, upon selection of a ConfigActivityGroup in the VM (through the ICollectionView), to copy the activities from the selected ConfigActivityGroup into a new ObservableCollection<string> in the VM (which in turn has it's own ViewSource and ICollectionView). Then, I could have the UI second list to bind to ICollectionView of the activities of the current ConfigActivityGroup. As such, my commands would modify the activities' ICollectionView. However, I ran into a roadblock when I tried to make a new activity for the current ConfigActivityGroup in which I couldn't set the activities' ICollectionView.CurrentItem to be a different activity string (since it's read only).

I thought one solution to that was to box up the activity string in an ActivityString class has a single string. Overall, I wasn't too happy with this method.

Second Solution I thought, was to make the List<string> in the ConfigActivityGroup to be an ObservableCollection<string>. That would simplify the VM. I hesitate to use this approach since the model is loaded from the database from a non-UI thread through magic json-deserialisation (MyCouch + CouchDB) and then problems arise (I think, from memory) when the ObservableCollection is accessed from a thread different from its creation thread. I thought that using one of the many thread-safe ObservableCollections was overkill.

Third Solution I thought while writing this question was to keep the model List<string> for the activities in the ConfigActivityGroup. Then, upon a ConfigActivityGroup being selected in its ICollectionView, initialising a CollectionViewSource/ICollection with the List<string> of activities directly as the source. That way the UI can bind to the activities directly and the UI can take care of editing the actual activity string; and the concept of a currently selected activity remains, which I can then delete using a command.

I think the third approach is the correct approach, but I am open to hearing what the community thinks. This is my first use of MVVM, and i'm trying to keep responsibilities separated and trying to use Commands as much as possible.

Extra data:

  • Once the ConfigActivityGroup is loaded from the database and put into the VM, it will not be changed by anyone else than the VM itself through the UI.
Mohamed Salah
  • 959
  • 10
  • 40
Peter pete
  • 704
  • 1
  • 7
  • 17
  • https://msdn.microsoft.com/en-us/library/system.windows.forms.listbox.selecteditem(v=vs.110).aspx bound to CurrentItem. Or, CommandParameter="{Binding}" to pass the model you wish to CRUD into your command's Execute method. Why not create a very simple prototype to try these out? –  May 07 '15 at 13:06

0 Answers0