The basic idea is that a user should be able to search Configurations based on Fields it has defined as a one-to-many relationship.
The fields table basically contains different name/value parameters for a Configuration. The design of the tables were inspired by the fact that different Configurations might have different parameters defined (otherwise this could all be in one flat table).
What I'd like to do is enable the user to search for Configurations based on parameters. So perhaps one of the parameters is Age... the user should be able to use the datafilter to say they want to see all the configurations where Age is greater than 25 for example.
The application uses RIA Services and Entity Framework. I have complete control over the database structure if a better one exists for the optimal solution.
I figured I would ask the experts. How would you accomplish this?
7 Answers, 1 is accepted
This cannot be done out-of-the box since it involves custom logic.
I believe that the only way to do this would be to use RadDataFilter in its Unbound Mode, i.e. with no source defined. When in Unbound Mode, you manually specify what the control will show in its UI, i.e. the names of some properties. They do not have to be real properties though.
Then you attach to the events of its FilterDescriptors property (CollectionChanged and ItemChanged) and perform a custom filtering on anything in the world that you like. In fact, the information inside this FilterDescriptors collection is what the user has defined through the UI and can be used for any purpose. Which in your case would be to search through these configuration objects.
If you want to use the Unbound Mode, you have to wait a week or so for the official Q3 release. There will be an example that demonstrates how to use the ItemPropertyDefinitions (the things you add in order to specify what will be shown in the drop-downs) of RadDataFilter.
Once you upgrade to Q3, let me know if you have problems with the Unbound Mode and we will think of something.
Greetings,
Ross
the Telerik team
I understand using the datafilter in the unbound mode. However, I'm a bit concerned about handling all of the search logic manually. Is there any mix of controls that might help here? What I'm asking is, is there any way to use datafilter in unbound mode with a domaindatasource to make the task easier?
I'm just thinking of implementing the custom search logic with all the options presented in datafilter using SQL or LINQ to objects, and it doesn't seem trivial.
If you could nudge me in the right direction here it would be well appreciated.
fyi... I'm using Silverlight, RIA Services, and SQL Azure
Thanks,
KB
If you bind RadDataFilter to a RadDomainDataSource, it will automatically "translate" its FilterDescriptors to an EntityQuery<TEntity> and send this filtering info to the server.
To explore the new RadDomainDataSource control in greater depth, please check its online examples and take a look at the following blog posts:
- Introducing RadDomainDataSource for Silverlight
- Loading data with RadDomainDataSource for Silverlight
- An MVVM Approach to Telerik Domain Services for Silverlight
- Creating CRUD application with RadDomainDataSource for Silverlight
- Why we have built RadDomainDataSource for Silverlight?
In the case of our data engine, we take the FilterDescriptors and we dynamically generate LINQ Lambda Expressions, we compile them at run-time and execute them against the data source, which is usually an IQueryable. In the case of RadDomainDataSource, we take the FilterDescriptors and translate them to an EntityQuery<T>.
So for example, if RadDataFilter has a descriptor which says:
Member=FirstName
Type=String
Operator=IsEqualTo
Value="John"
we will take it and create something like this:
EntityQuery<Person> query = this.myDomainContext.Persons;
var newQuery = query.Where(person => person.FirstName == "John");
You can write your very own program logic that takes a descriptor and translates it to anything that you need. This will be according to the particular data source that you have.
This entire process is very far from trivial since it involves heavy work with LINQ Expressions and Expression Visitors, but it is not impossible nonetheless.
Or I have another idea, you can read all the data stored in the FilterDescriptors, i.e. Member, Operator, Value and so on, pack it into some kind of comma-delimited long string and pass this huge string as a QueryParemeter of your server-side query method. Then on the server, take the huge string, dis-assemble it, read the filtering info that the user is sending from the client and prepare the respective query against your data source. With this approach you will be performing all the logic on the server, which might be easier form you.
I hope this helps.
Ross
the Telerik team
Register for the Q2 2011 What's New Webinar Week. Mark your calendar for the week starting July 18th and book your seat for a walk through of all the exciting stuff we will ship with the new release!
Even if I handled the ItemPropertyDefinitions myself, there still seems to be no way to build FilterDescriptors that can be used to query on an associated EntityCollection defined by a one-to-many relationship ( see my data structure in the first post). While it does seem possible to set the PropertyPath of a FilterDescriptor to search for an associated one-to-one relationship.
Do I have this correct?
If so, I am left with passing something like the FilterDescriptors to the server, and building up my query there. Would it be possible to share some of the code on how to build up a LINQ query based on your filter descriptors to get me started? I understand LINQ, but the task seems somewhat daunting at the moment.
At least that would save a ton of time...
You are right. RDDS cannot do such complex custom things.
BUT!
We have publicly exposed our Where methods. Here is one of the overloads (in Telerik.Windows.Data.QueryableExtensions):
public
static
IQueryable Where(
this
IQueryable source, CompositeFilterDescriptorCollection filterDescriptors)
{
if
(filterDescriptors.Count() > 0)
{
var parameterExpression = Expression.Parameter(source.ElementType,
"item"
);
var expressionBuilder =
new
FilterDescriptorCollectionExpressionBuilder(parameterExpression, filterDescriptors);
expressionBuilder.Options.LiftMemberAccessToNull = source.Provider.IsLinqToObjectsProvider();
var filterLambda = expressionBuilder.CreateFilterExpression();
//TODO: Delegate the entire job to the FilterDescriptorCollectionExpressionBuilder just like the Sort is implemented.
if
(filterLambda !=
null
)
{
return
source.Where(filterLambda);
}
}
return
source;
}
So here is what this method does. You supply an IQueryable and a collection of FilterDescriptors. It takes this collection and based on it appends one or more Where method calls on the IQueryable and then returns it.
So the easiest way for you would be to provide some kind of dummy (that is -- hollow, doing nothing) IQueryable to this method along with the FilterDescriptors and let it "do its thing" over this IQueryable. Then you can take this resulting IQueryable and read its Expression property. This is the LINQ Expression that our data engine has generated. The whole purpose of this dummy hollow IQueryable is for our data engine to create its Expression over it. Have in mind though that you might have to make the dummy IQueryable behave like its Provider is LinqToEntities and not LinqToObjects, since the generated expressions are somewhat different. When we detect LinqToObjects we add specials checks for null in all expression since SQL server does not care about nulls, but .NET does.
I checked your account and saw that you have our source code. If you want to delve into what we do to create this expression start with the method that I pasted above and drill down. Basically, the classes that interest you will be all classes inheriting from FilterExpressionBuilder.
But I think that if you use our Where method and get the Expression that would be enough for you.
You can even use Expression Visitors and re-visit the expression that we have generated to suit your particular needs.
I hope this helps. All the best,
Ross
the Telerik team
Register for the Q2 2011 What's New Webinar Week. Mark your calendar for the week starting July 18th and book your seat for a walk through of all the exciting stuff we will ship with the new release!
Thank you
Swetha