Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Filtering in MVVM architecture

DZone's Guide to

Filtering in MVVM architecture

· Database Zone ·
Free Resource

Compliant Database DevOps and the role of DevSecOps DevOps is becoming the new normal in application development, and DevSecOps is now entering the picture. By balancing the desire to release code faster with the need for the same code to be secure, it addresses increasing demands for data privacy. But what about the database? How can databases be included in both DevOps and DevSecOps? What additional measures should be considered to achieve truly compliant database DevOps? This whitepaper provides a valuable insight. Get the whitepaper

Wpf has great filtering capabilities based on CollectionViewSource class, but how can we use effectively in MVVM architecture? First of all we need to decide who has the responsibility of filtering data, and clearly the answer is: the ViewModel. VM  usually exposes an ObservableCollection<T> property for collections of items, the view bind to it and everything goes smooth, until you need to set a filter on it. A possible solution is to grab a reference to an ICollectionView in the viewmodel and manipulate that object.

   1: ListCollectionView lcv = CollectionViewSource.GetDefaultView(myCollection) as ListCollectionView;

2: lcv.SortDescriptions.Add(new SortDescription(…));


I do not like very much this approach, are you sure that a valid default view exists during a UnitTest? So lets examine another possible solution.

Suppose you have a view that has a ListView currently bound to a property of ViewModel called Links, and this property is an ObservableCollection<T>, suppose also that you need to filter content based on a property called Status. What I want is “no code” on the View, and minimum impact on the already existing view, I want also the ability to test the filter function with a unit test.

For the first requirements, it is enough to expose to the view “something” bindable in the same property name (Links), since my ViewModel has an ObservableCollection<SingleAnalysisLink> called Links, I changed the viewmodel in this way.

   1: internal ObservableCollection<SingleAnalysisLink> InnerLinks { get; set; };

2:

3: internal CollectionViewSource CvsLinks{get; set; }

4:

5: public ICollectionView Links

6: {

7: get { return CvsLinks.View; }

8: }


The real ObservableCollection is now internal, then I added a CollectionViewSource property and finally the Links readonly property that return the View of the CollectionViewSource property (that is perfectly bindable). Now during VM initialization I need to setup everything.

   1: InnerLinks = new ObservableCollection<SingleAnalysisLink>();

2: CvsLinks = new CollectionViewSource();

3: CvsLinks.Source = InnerLinks;

4: CvsLinks.Filter += ApplyFilter;


I create the ObservableCollection, the new CollectionViewSource and add the collection to the source, then bound the event ApplyFilter wrote this way.

   1: void ApplyFilter(object sender, FilterEventArgs e)

2: {

3: //each item is a specific object

4: SingleAnalysisLink si = (SingleAnalysisLink) e.Item;

5: if (StatusFilter == null)

6: {

7: e.Accepted = true;

8: } else

9: {

10: e.Accepted = si.Status == StatusFilter;

11: }

12: }

13: public SingleAnalysisStatus? StatusFilter

14: {

15: get { return _statusFilter; }

16: set {

17: this.Set(p => p.StatusFilter, value, ref _statusFilter);

18: OnFilterChanged();

19: }

20: }

21:

22: private SingleAnalysisStatus? _statusFilter;

23:

24: private void OnFilterChanged()

25: {

26: CvsLinks.View.Refresh();

27:

28: }


The function ApplyFilter filters object based on another property of the VM called StatusFilter, of the same type of the enum property used in the bound object. In the setter part of the StatusFilter property simply call a function that refresh the view. Now I can simply add a combo in the View, bind the SelecteValue property to the StatusFilter VM property and without any other change I’ve added filtering capabilities to the View.

The cool part is that I’m able to write unit test that verify filtering capabilities.

   1: ...

2: sut.AddUrlToAnalyze(link);

3: sut.AddUrlToAnalyze(link2);

4:

5: link2.Status = SingleAnalysisStatus.Match;

6: sut.StatusFilter = SingleAnalysisStatus.Match;

7: sut.Links.OfType<SingleAnalysisLink>()

8: .Count().Should().Be.EqualTo(1);


I’ve added two SingleAnalysisLink to the VM, then change the status of only one of them to Match, set a filter to show only item with status == Match and assert that the count of items of the view is Equal To 1.

Compliant Database DevOps and the role of DevSecOps DevOps is becoming the new normal in application development, and DevSecOps is now entering the picture. By balancing the desire to release code faster with the need for the same code to be secure, it addresses increasing demands for data privacy. But what about the database? How can databases be included in both DevOps and DevSecOps? What additional measures should be considered to achieve truly compliant database DevOps? This whitepaper provides a valuable insight. Get the whitepaper

Topics:

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}