In this article, the filter and pipeline patterns are optimized with code reduction using lambda expression (shortcuts for anonymous method) as concrete filter condition. To demonstrate the concept, the sample WPF UI application was created.
Introduction
This article demonstrates filter pattern with generic lambda expression on WPF. Filter pattern along with pipeline is heavily used in data driven application. With C# lambda expression, the code can be shorted and generalized.
Pipeline and Filter Pattern
Traditionally, filter pattern interface is implemented for every new filter. Instead of implementing interface for every filter condition, the generic lambda expression can be used as input to filters pipeline. As a result, there will be less code. Given below is a class diagram:
ConditionAggregator
is a pipeline class where it stores collection of Condition<T>
. Filter<T>
owns ConditionAggregator
or Condition<T>
to apply filter conditions on data collection. When Filter<T>
apply function is called, ICondition<T>
check method is executed. ConditionAggregator<T>
has event OnFilterChanged
. It is triggered when the collection or condition value is changed at view model classes. The next section will describe view model usage filter pattern.
Using the Code
Usage in View Model
MVVM framework explanation can be read in this link. In MVVM, one of the responsibilities of the view model is to handle user interaction and data changes. In our case, the filter condition value changes should be passed to business layer to apply filters on given data collection. The condition value changes in view model will trigger ConditionAggregator<T> OnFilterChanged
event where filter apply method is subscribed. Below is a class diagram of view model:
Employee
entity class is created to contain employee
information. The generic T
type of filter design pattern will be replaced with Employee
class. EmployeeList
holds list of employee
data and Filters
to apply. The class constructor receives condition list and passes to filter list.
public EmployeeList(IEmployeesRepository repository,
ConditionAggregator<employee> conditionAggregator)
{
this.repository = repository;
this.filters = new ConcreteFilter<employee>(conditionAggregator);
conditionAggregator.OnFilterChanged += this.FilterList;
_ = initAsync();
}
FilterList
method is subscribed to OnFilterChanged
event to apply filters on data when condition or value changed event occurs.
private void FilterList()
{
this.Employees = this.filters.Apply(this.employeesFullList);
}
EmployeesViewModel
is connected to UI. In this sample application, the only one EmployeeTypeselected
property filter is demonstrated but the many filters can be passed to ConditionAggregator
. The following code snippet is a constructor method where Filter
condition is registered.
public EmployeesViewModel(IEmployeesRepository repository)
{
this.repository = repository;
Condition<employee> filterEmployee =
new Condition<employee>((e) => e.employeeCode == this.EmployeeTypeSelected);
this.conditionAggregator =
new ConditionAggregator<employee>
(new List<condition<employee>> { filterEmployee });
this.EmployeeList = new EmployeeList(repository, this.conditionAggregator);
}
The condition is given as lambda expression. It can be as many as necessary since ConditionAggregator
constructor accepts the List
of filter conditions. The primary goal of code reduction of creating specific filter condition class is achieved.
Architecture of Sample Application
WPF.Demo.DataFilter
project is WPF UI view. It has one grid
and one combobox
to filter. WPF.Demo.DataFilter.ViewModels
project handles data and filter changes and reloads data for UI update. WPF.Demo.DataFilter.Common
project is full implementation of Filter
and pipeline patterns. WPF.Demo.DataFilter.DAL
loads simple json file as data store.
This is the main UI::
History
- 29th July, 2020: Initial version