Click here to Skip to main content
13,899,494 members
Click here to Skip to main content
Add your own
alternative version


97 bookmarked
Posted 30 Jun 2010
Licenced CPOL

Visual Expression Builder for Dynamic Linq

, 2 Feb 2012
Rate this:
Please Sign up or sign in to vote.
Let your users create their own Linq filters with this MVVM WPF tool you can include in your application

Updated! The source code has been updated to make the dynamic types more robust!

Table of Contents



Linq is a great way to declaratively filter and query data in in a Type-Safe, Intuitive, and very expressive way. However, your users should not have to call you every time they have a new way to filter or query their data.

So here is a way for your users to filter their data no matter where that data comes from. Whether its Linq2SQL or an in-memory structure, now your users can have the power.

It is the most valuable feature that you can add for your users in 4 lines of code.
I would also recommend actually reading the code. The entire project has only 233 lines of code in it - that's including the XAML.

Using the Code

The real functionality is in the two classes in the ViewModel. The UserControl is just a glorified DataTemplate for the ExpressionList.


I know that most of you will want to know how this bad boy works, so you can use the same techniques in your own solutions. However, you could just use the UserControl as-is by adding it straight into your XAML, and binding it to an ExpressionList, so that is what I will start with.

<uc:FilterUserControl DataContext="{Binding ExpressionList1}" />

Somewhere in your ViewModel:

public     ExpressionList ExpressionList1    { get; set; } 
ExpressionList1 = new ExpressionList() {Type=typeof(Contact)} ; 

Then once your user selected all of the filters, you get your final query like this:

var filteredContacts =


I first tried many other Dynamic Linq solutions. There is the "DynamicLinq" project explained in ScottGu's Blog which allows you to parse expressions in strings. So your users could write their own expressions in a text box which you could then apply to your Linq. I learned a lot about expressions from their implementation.

Then, there is the solution I almost used - The Dynamic Linq tool from the VB tool. It did almost exactly what I needed it to do, and you will notice that it looks a lot like the tool that I ended up creating which I am showing here today. The biggest problem is that it was written for WinForms and the functionality was too interwoven with the presentation. I actually needed one of the main benefits of MVVM (previously MVP) - The ability to persist the state even when the UI disappears and easily create default and saved sets of filters.

What Exactly is Happening?

As I said before, the real functionality is in the two classes in the ViewModel (I considered the builtin Expression class to be my model):

  • ExpressionVM contains the necessary data and functionality to create an expression with one comparison.
  • ExpressionList is an observable collection of ExpressionVMs with one property to create a lambda expression out of all the child expressions.

ExpressionList is Just an ObservableCollection<ExpressionVM> with two important properties:

  • Type Type - which is used in making the expression and used to populate the AvailableProperties in the ExpressionVMs.
  • Expression CompleteExpression - which combines the Expressions from all of the ExpressionVMs into one lambda expression.

ExpressionVM's members are:

  • Type ObjectType - The type being filtered (usually set from the ExpressionList)
  • PropertyInfo PropertyInfo - The information about the property that the user chose to compare on this line.
  • string PropertyName - (readonly) comes from the PropertyInfo.
  • Type PropertyType - (readonly) comes from the PropertyInfo.
  • CombineOperator - chosen by the user to determine how to combine this line with the previous line
  • CompareOperator - chosen by the user to determine how to compare the property with the constant
  • object Value - The constant to be used in the comparison
  • AvailableCombineOperators, AvailableCompareOperators, AvailableProperties - lookup list to populate the ComboBoxes.
  • GetSupportedTypes - So that we don't give the user the option to filter by image :)
  • MakeExpression -Creates an expression based on the choices of the user

The Meat (or Tofu) and Potatoes of the Solution

The most interesting code is contained in two functions MakeExpression and the getter for CompleteExpression.

public LambdaExpression MakeExpression(ParameterExpression paramExpr = null)
    if(paramExpr == null) paramExpr = Expression.Parameter(ObjectType, "left");
    var callExpr = Expression.MakeMemberAccess(paramExpr, PropertyInfo);
    var valueExpr = Expression.Constant(Value, PropertyType);
    var expr = Expression.MakeBinary((ExpressionType)CompareOperator, 
        callExpr, valueExpr);
    return Expression.Lambda( expr, paramExpr);
public Expression CompleteExpression
        var paramExp = Expression.Parameter(Type, "left");
        if (this.Count == 0) return Expression.Lambda
        (Expression.Constant(true), paramExp);
        LambdaExpression lambda1 = this.First().MakeExpression(paramExp);
        var ret = lambda1.Body;
        foreach (var c in this.Skip(1))
            ret = Expression.MakeBinary((ExpressionType)c.CombineOperator, 
        ret, c.MakeExpression(paramExp).Body);
        return Expression.Lambda(ret, paramExp);

The CompleteExpression creates an input parameter out of the ObjectType and a lambda out of the first ExpressionVM. Then it loops through the rest of the ExpressionVMs appending the Expressions it gets from their MakeExpressions to the lambda based on their CombineOperator.

Other Interesting Code Snippets

I provide lookup lists for each ComboBox.

The AvailableProperties is populated every time the ObjectType changes.

set { 
        _ObjectType = value;
        AvailableProperties = from p in value.GetProperties()
                    where GetSupportedTypes().Contains(p.PropertyType)
                    select p;

The CombineOperator and the CompareOperator are both enums. So their lists are generated on the fly like this:

public Array AvailableCompareOperators
    get { return Enum.GetValues(typeof(ComparisonOperators)); }

To Do

Yes, there is still a lot left to do, and there is a lot of room for improvement.
Here is a short list that I came up with:

  • Add more operators
  • Allow ANDs and ORs to be nested
  • Allow sub properties to be selected
  • Make WPF select specialized templates based off the PropertyType


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Rabb Moshe Plotkin
United States United States
Co-director of Chabad Student Center @ SUNY New Paltz
Lecturer of Computer Science @ SUNY New Paltz

You may also be interested in...

Comments and Discussions

QuestionHow to input an expression? Pin
Member 110171727-Oct-14 9:30
memberMember 110171727-Oct-14 9:30 
QuestionGetting Started with the expression builder Pin
Member 946477722-Jul-14 4:47
memberMember 946477722-Jul-14 4:47 
Questionstring value could be null Pin
SLX6-Mar-14 10:25
memberSLX6-Mar-14 10:25 
QuestionDataTypes Pin
CodePug1-Aug-13 8:16
memberCodePug1-Aug-13 8:16 
AnswerRe: DataTypes Pin
Rabb Moshe Plotkin1-Aug-13 9:35
memberRabb Moshe Plotkin1-Aug-13 9:35 
GeneralRe: DataTypes Pin
CodePug2-Aug-13 6:18
memberCodePug2-Aug-13 6:18 
I may not be expressing the problem clearly.

I'm assuming "Contact" is a class, since it's capitalized. But I don't know what conventions you're using, so in the absence of a definition, it could be an integer, for all I know. You say that any type will work.

You refer to it as an object. Is it an object reference or a class reference?

What relationship does "contacts" have to "Contact"? I was assuming that it was some sort of collection of contact objects, but that's just a guess based on the conventions I use. If it's a collection, what kind of collection? Does it matter?

In my code project, "Contact" is a class representing a business object, which inherits from Rocky Lhotka's CSLA Framework. "contacts" is an ObservableCollection of Contact objects. In debugging mode, I can see that AvailableProperties is populated with the properties of my class, but the control doesn't display. Also, ".Where' is not a method in my collection. This may be my sketchy knowledge of Linq surfacing, but "contacts.Where" seems to indicate something that has "Where" as a method, not just any datatype.
QuestionIt doesnt work what is my mistake ? Pin
sven197825-Nov-12 7:57
membersven197825-Nov-12 7:57 
AnswerRe: It doesnt work what is my mistake ? Pin
sven197826-Nov-12 7:17
membersven197826-Nov-12 7:17 
GeneralRe: It doesnt work what is my mistake ? Pin
Rabb Moshe Plotkin1-Aug-13 9:40
memberRabb Moshe Plotkin1-Aug-13 9:40 
QuestionI added 'StartsWith' and 'EndsWith' to MakeExpression Pin
Paul Brower23-Mar-12 9:27
memberPaul Brower23-Mar-12 9:27 
QuestionWinForms version? Pin
Paul Brower21-Mar-12 4:27
memberPaul Brower21-Mar-12 4:27 
AnswerRe: WinForms version? Pin
Paul Brower22-Mar-12 2:29
memberPaul Brower22-Mar-12 2:29 
QuestionRe: WinForms version? Pin
bsculley26-Mar-12 12:34
memberbsculley26-Mar-12 12:34 
AnswerRe: WinForms version? Pin
Paul Brower26-Mar-12 15:33
memberPaul Brower26-Mar-12 15:33 
GeneralRe: WinForms version? Pin
wvd_vegt27-May-13 23:53
professionalwvd_vegt27-May-13 23:53 
GeneralRe: WinForms version? Pin
goud12329-May-14 20:53
membergoud12329-May-14 20:53 
QuestionProject VS Pin
mdenicola1-Mar-12 6:42
membermdenicola1-Mar-12 6:42 
AnswerRe: Project VS Pin
ksecrist19-Jul-12 10:06
memberksecrist19-Jul-12 10:06 
GeneralMy vote of 5 Pin
Dean Oliver5-Feb-12 23:11
memberDean Oliver5-Feb-12 23:11 
GeneralMy vote of 4 Pin
HoyaSaxa933-Feb-12 6:37
memberHoyaSaxa933-Feb-12 6:37 
QuestionSample Project Pin
Shaun Brown16-Aug-11 6:45
memberShaun Brown16-Aug-11 6:45 
GeneralContains/Like Pin
Neil Alderson21-Jul-10 0:11
memberNeil Alderson21-Jul-10 0:11 
GeneralRe: Contains/Like Pin
Rabb Moshe Plotkin21-Jul-10 2:28
memberRabb Moshe Plotkin21-Jul-10 2:28 
GeneralRe: Contains/Like Pin
Neil Alderson6-Aug-10 1:33
memberNeil Alderson6-Aug-10 1:33 
GeneralRe: Contains/Like Pin
Rabb Moshe Plotkin6-Aug-10 2:20
memberRabb Moshe Plotkin6-Aug-10 2:20 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web05 | 2.8.190306.1 | Last Updated 2 Feb 2012
Article Copyright 2010 by Rabb Moshe Plotkin
Everything else Copyright © CodeProject, 1999-2019
Layout: fixed | fluid