views:

3472

answers:

3

I have a combo box in Silverlight. It has a collection of values built out of the properties of one of my LINQ-to-SQL objects (ie Name, Address, Age, etc...). I would like to filter my results based off the value selected in a combo box.

Example: Say I want everyone with a last name "Smith". I'd select 'Last Name' from the drop down list and enter smith into a textbox control. Normally I would write a LINQ query similar to...

var query = from p in collection
where p.LastName == textbox.Text
select p;

Is it possible to decide the property dynamically, maybe using Reflection? Something like

var query = from p in collection
where p.(DropDownValue) == textbox.Text
select p;

+1  A: 

Scott Guthrie has a short series on dyamically built LINQ to SQL queries:

http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx

That's the easy way...then there's another way that's a bit more involved:

http://www.albahari.com/nutshell/predicatebuilder.aspx

Kev
These articles are perfect if you're working with ASP.NET applications, good to know, thanks for that, unfortunately with Silverlight, System.Windows.Threading does not support some of the methods used in the Dynamic LINQ Library
EC182
Ah...the Silverlight tag was in my blindspot.
Kev
+7  A: 

Assuming:

public class Person
{
    public string LastName { get; set; }
}

IQueryable<Person> collection;

your query:

var query =
    from p in collection
    where p.LastName == textBox.Text
    select p;

means the same as:

var query = collection.Where(p => p.LastName == textBox.Text);

which the compiler translates from an extension method to:

var query = Queryable.Where(collection, p => p.LastName == textBox.Text);

The second parameter of Queryable.Where is an Expression<Func<Person, bool>>. The compiler understands the Expression<> type and generates code to build an expression tree representing the lambda:

using System.Linq.Expressions;

var query = Queryable.Where(
    collection,
    Expression.Lambda<Func<Person, bool>>(
        Expression.Equal(
            Expression.MakeMemberAccess(
                Expression.Parameter(typeof(Person), "p"),
                typeof(Person).GetProperty("LastName")),
            Expression.MakeMemberAccess(
                Expression.Constant(textBox),
                typeof(TextBox).GetProperty("Text"))),
        Expression.Parameter(typeof(Person), "p"));

That is what the query syntax means.

You are free to call these methods yourself. To change the compared property, replace this:

typeof(Person).GetProperty("LastName")

with:

typeof(Person).GetProperty(dropDown.SelectedValue);
Bryan Watts
Brilliant Answer... Just what I was looking for... Thanks Brian...
gg
A: 

You can also use the library I created: http://tomasp.net/blog/dynamic-linq-queries.aspx. You would store the properties in ComboBox as lambda expressions and then just write:

var f = (Expression<Func<Product, string>>)comboBox.SelectedValue;
var query =
    from p in collection
    where f.Expand(textBox.Text)
    select p;
Tomas Petricek