6

I am creating a little stock-management tool for private use.

I have different views, which need similar but different filters. As an example I have a "current stock" list where I can filter for supplier, product group and name. I have the same list again but with additional filters for certain boolean flags. I am going to create a little statistic view where I will need all of the mentioned filters and some more like date range.

An last but not least I am creating a little csv Export where I have similar requirements as in the statistic view.

It isn't much but enough to think about a decent architecture. If you do it right on a small scale, chances are you do it right on bigger projects.

I use WPF with MVVM.
So far I have thought of some ways to tackle my problem:

  1. Individual filter for each view: It is of course the most flexible variant but also leads to the most work if something concerning the filters is changed.

  2. Filter generator: A control gets generated according to the configuration, sounds good but i loss the flexibility of styling the filter according to the view (i could add this to the configuration, but it would still lose me the advantages of xaml) and I can't really preview it in xaml during design time.

  3. Creating a single ViewModel which contains all possible filters and Controls + ViewModels for each filter type (Checkbox, Combobox, Textbox). This approach would allow my to simply style the filter in xaml by using the filter controls for each view while capsuling the filter VM in one implementation.

For me the 3. option looks preferable but as i have never done anything alike, so I am looking for some feedback on how such a problem is usually approached or if some related pattern exist.

3 Answers 3

1

I would use full MVVM for this solution.

  • Filter model and it's subclasses (e.g. XYZFilter) control how to apply the filter to your data and can easily be tested
  • XYZFilterViewModel takes care of any UI bridging needs
  • XYZFilterView takes care of the UI itself

This allows you to re-use filters across screens. Whether you code View first or ViewModel first, the same mechanisms you use for the full page can work for small pieces of the page. This is a perfect example where you can easily do this. By re-using the individual views and view-models, you also ensure a consistent user experience across your application.

Regarding your second option, having custom XAML for each and every page may present your user a negative experience. When users see the same controls on different pages, their confidence increases since they know they only have to learn the control once.

I'm really having a hard time understanding what you mean in your third option. Are you talking about one ViewModel that contains properties for all the filters in your application? How would adding or removing filters work? I feel like I am missing something because it sounds like a maintenance nightmare.

0

I would start by determining the collection types to be used throughout the application, trying to keep only one 'Major' collection of data where possible.

From there when the new 'Major' collection is set, it can fire an event to any listener that may show a different view. (Events are an Observer pattern). Each observer then has addressibility to the 'Major' collection and can wrap it with a CollectionViewSource which allows for excellent filtering ability. Each view having different filtering requirements. Filtering for other views only happens when that view receives focus.

Each view then can either add columns to the View or Hide columns not needed.

There are tricks to this whereby you can use functions in a method to allow for filtering a grid based on what 'a caller' to determine what is needed to filter. All filtering is then able to be abstracted to the app.config file so that new dynamic filters can be added at will based on values the user places in the config file, this allows for new behavior without recompiling projects.

From there, as the application grows, you may want to add a 'repository' layer which pretty much moves all data access and business logic to one place one time. All views then would simply call the 'repository' functions to get everything they need.

Using LINQ and CollectionViewSource objects bound to datagrids is one of the best combination of tools out there. In addtion where possible I really like Entity Framework as well if back end is SQL. If you are dealing with JSON then JSON.NET is the best tool for that.

1
  • I am already using a similar architecture (CollectionViewSource on an EF Source). What i am looking for architecture to easily create new filter controls and connect them to the corresponding VM filter logic with as little code duplication as possible.
    – lolsharp
    Commented Oct 16, 2015 at 19:05
0

Create smallest "filter-units".

Checkbox        -> BooleanFilterViewModel  -> BooleanFilter   
DatePicker      -> DateTimeFilterViewModel -> DateTimeFilter  
(Two textboxes) -> IntegerRangeViewModel   -> IntegerRange  

Then you can create different views by combining all filters together.
It will remain flexible, because you have smallest unit which can be added, removed, replaced

If possible introduce abstractions instead of concrete types for viewmodels and filters

IDateTimeFilterViewModel
IIntegerRangeFilterViewModel

IDateTimeFilter
IIntegerRangeFilter

Abstractions give you possibility to reuse same viewmodels/views filters which have different behaviour.

For example

public class TodayStockViewModel
{
    public IIntegerRangeFilterViewModel PriceFilter { get; set; }
    public IDateTimeFilterViewModel TimeFilter { get; set; }
    public IBooleanFilterViewModel OnlyDomesticCompaniesFilter { get; set; }
}

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