简体   繁体   中英

One ViewModel containing a collection of ViewModels, different Views depending on value of ViewModel property

I am new to the MVVM-pattern, and am trying out Caliburn.Micro on a project.

I want to have one ViewModel (which contains a collection of ViewModels) shared by multiple Views, where each view only displays items which have a certain value on one of it's properties.

To get specific, I am using a service which allows me to monitor different values that update frequently. I then get an object of type MonitoredItem, which contains a property of type DataValue , which in turn contains an object for the Value and a property for the value's datatype.

So far I have a MonitoredItemViewModel which uses this service's MonitoredItem class as it's model, and a MonitoredItemsViewModel which contains BindableCollection<MonitoredItemViewModel> MonitoredItems, and commands for adding/removing items.

I also have a MonitoredItemsView where I can see all the items I am currently monitoring.

How do I go about splitting up the view, so that I can have all MonitoredItems where DataValue is an integer/float/double displayed in one area in my window, boolean values displayed somewhere else etc?

Don't do it in the view, instead expose different collections on your ViewModels according to what you need to filter.

This can be done either as known collections, eg

public ObservableCollection<MonitoredItemViewModel> ItemsWhereFooIsBar ...
public ObservableCollection<MonitoredItemViewModel> ItemsWhereFooIsntBar ...

or you could do it more generically to return filtered collections on demand

public ObservableCollection<MonitoredItemViewModel> GetItems(Func<DataValue, bool> matches)
{
   //Filter collection with 
   return ... allItems.Where(x=>matches(x))... ;
}

and call via

GetItems(x=>x.Foo == Bar)

The problem you are going to have is when the items change and should switch from collection to collection. If you were using ReactiveUI this would be incredibly easy as you can use Rx to trigger its built in item tracking and also use its .CreateDerivedCollection(...) to build the new collections automatically (hint, hint :-))

If not then you have a few choices.

  • You can derive a class from ObservableCollection so that as well as being notified via CollectionChanged when new items are added or removed, or also get notified when the properties of the items change as well.
  • Or you could make your ItemViewModel immutable so that its properties never change, but instead you drop the old item and add an updated one into the correct collection.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM