Should Item Grouping/Filter be in the ViewModel or View layer

mvvm

I'm in a situation where I have a list of items that need to be displayed depending on their properties. What I'm unsure of is where is the best place to put the filtering/grouping logic of the viewmodel state?

Currently I have it in my view using converters, but I'm unsure whether I should have the logic in the viewmodel?

e.g.

ViewModel Layer:

class ItemViewModel
{
    DateTime LastAccessed { get; set; }
    bool IsActive { get; set; }
}

class ContainerViewModel
{
     ObservableCollection<Item> Items {get; set;}
}

View Layer:

<TextView Text="Active Items"/>
<List ItemsSource={Binding Items, Converter=GroupActiveItemsByDay}/>
<TextView Text="Active Items"/>
<List ItemsSource={Binding Items, Converter=GroupInActiveItemsByDay}/>

or should I build it like this?

ViewModel Layer:

class ContainerViewModel
{
   ObservableCollection<IGrouping<string, Item>> ActiveItemsByGroup {get; set;}
   ObservableCollection<IGrouping<string, Item>> InActiveItemsByGroup {get; set;}
}

View Layer:

<TextView Text="Active Items"/>
<List ItemsSource={Binding ActiveItemsGroupByDate }/>
<TextView Text="Active Items"/>
<List ItemsSource={Binding InActiveItemsGroupByDate }/>

Or maybe something in between?

ViewModel Layer:

class ContainerViewModel
{
   ObservableCollection<IGrouping<string, Item>> ActiveItems {get; set;}
   ObservableCollection<IGrouping<string, Item>> InActiveItems {get; set;}
}

View Layer:

<TextView Text="Active Items"/>
<List ItemsSource={Binding ActiveItems, Converter=GroupByDate }/>
<TextView Text="Active Items"/>
<List ItemsSource={Binding InActiveItems, Converter=GroupByDate }/>

I guess my question is what is good practice in terms as to what logic to put into the ViewModel and what logic to put into the Binding in the View, as they seem to overlap a bit?

Best Answer

Grouping and filtering is one of the explicit purposes of a View Model as opposed to just using a Model. The view model takes the data from the model and organizes it precisely for the given view.

That means where a model may often be a robust data representation, and the view only needs a subsection or aggregate of that model, the view model exists to give you the data your view needs so that your view does not need to do that leg work.

It can be confusing because often times people write code that has the view going straight to the model and in these cases the view does end up responsible for this work, but if you do use view models as an intermediary, you don't need to and shouldn't be doing this non-presentational work in the view.

Related Topic