6

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?

4

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.

2
  • Yes, however, what if I want a view for the same view model that does not involve grouping? In my specific case I use the same view model on both Android and Windows Phone, however, due to platform differences, one of them should not group items. Using the approach with converters I could use the same view model for both platforms. Not saying you are wrong, just arguing the other side. – ronag Aug 2 '13 at 15:56
  • 1
    @ronag Now you lost the entire purpose of the view model though and you may as well have both views sharing the same model and not have the extra cruft of a view model if you want to go this way. The purpose of a view model is that it should be 1-to-1 with a given view, doing the leg work for that one view, other views get other view models even though they share the same models. – Jimmy Hoffa Aug 2 '13 at 15:59
1

I'm not sure there is a single correct answer here but I prefer to do the grouping in the XAML using a CollectionViewSource where I can. For example, something like the following might work for you:

<CollectionViewSource x:Key="groupedItems" Source="{Binding Items}">
    <CollectionViewSource.GroupDescriptions>
        <PropertyGroupDescription PropertyName="IsActive"/>
        <PropertyGroupDescription PropertyName="LastAccessed"/>
    </CollectionViewSource.GroupDescriptions>
</CollectionViewSource>

<ListBox ItemsSource="{Binding Source={StaticResource groupedItems}}"/>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.