Bindable LINQ: Dependencies
Update: SyncLINQ has been released under the name Bindable LINQ, and is available from CodePlex
My last SyncLINQ commit introduces a working implementation of dependencies. Put simply, you can write normal looking LINQ queries like this:
listBox.ItemsSource = from c in contacts.AsBindable()
where c.FullName.StartsWith(textBox1.Text)
select c;
And by looking at the expressions, SyncLINQ will automatically figure out that:
- The query is dependant upon the FullName property of each item in the collection
- The query is dependant upon the Text property of a WPF TextBox
If you have used the instant search features in Live Messenger or Microsoft Outlook, you’ll begin to recognize some scenarios where this is useful.
For example:
- As you type in the TextBox, the results are filtered
- If you rename items, they would disappear if the new name no longer matched what you typed in the TextBox
Without SyncLINQ, even simple UI experiences like this can be surprisingly hard to implement properly. What happens when contacts go online or offline while a search is happening? What if they change their name?
Take it even further: What if you wanted to group the results, order them, or project them into a new object? Not a problem for SyncLINQ:
listBox.ItemsSource = from c in contacts.AsBindable()
where c.FullName.StartsWith(textBox1.Text)
group c by c.Company into group
select new {
Company = group.Key,
Contacts = group.OrderBy(c2 => c2.FullName)
};
My challenge to you: how would you implement that without SyncLINQ?
I first wrote about my thinking behind dependencies here. I still plan to allow the addition of external dependencies (as that post suggested), but most can be figured out by parsing the expression trees like I am above.
There’s a little more work to do with dependencies, and a couple of simple query operators I want to finish, and then V1.0 will ship - hopefully early next week.
Oh, and don’t forget: I’ll be demonstrating SyncLINQ at Code Camp OZ if you’d like to see it in action.
Filed under: Bindable LINQ

Step 1: Set the text box to AutoPostBack=”true” and add a OnTextChanged event handler
Step 2: Have the event handler create the data context, perform the query against the text box value and doing basically what you’re doing in the SyncLinq statement
Step 3: ??
Step 4: Profit!
Or alternatively you could have a PageMethod which you call form javascript to make an AJAX request to prevent the visual postback or use UpdatePanels if your wanting to do lazy AJAX.
Yeah… pick the web dev, I wouldn’t even have a clue if there’s a Win Forms event that you could use to do this, but I’m sure it’d be something similar, without creating a new data context each time as it doesn’t have the state management differences of a web form
Hi Aaron,
With WPF/Windows Forms, because of the stateful nature of the application, it would be a bit more involved. Approximately:
1) You’d setup your query, and add the results to an ObservableCollection or BindingList
2) In a “refresh” method, you’d clear the ObservableCollection and re-run the query and add the items to it again
3) You’d handle the TextChanged of the textbox to call Refresh
4) You’d subscribe to the PropertyChanged event on every item in the collection, and unsubscribe when the item is removed. When the event is raised, you’d call Refresh. Make sure to use Weak References in the subscriptions or you’ll get memory leaks.
5) You’d have to subscribe to the CollectionChanged event on your underlying collection, in case new contacts are added while the filter is in effect. Make sure to use Weak References in the subscriptions or you’ll get memory leaks. When the event is raised, you’d call Refresh()
And all of these Refreshes mean the user loses where they are currently at (i.e., any selections would be lost, the scroll position would be lost, etc.). To do it properly, you should only add or remove items, not refresh the whole query. You can’t do that with OOTB with LINQ, and it’s a lot more work to wrap.
For WPF, using a CollectionViewSource and a Filter can very easily do the ‘instant search’ of SyncLinq (see Bea Costas blog, who is on the WPF team I believe, http://www.beacosta.com/blog/?cat=13)?
Online/Offline? Well, providing your objects have PropertyChanged thing, and you’re using a TreeView that groups based on Contact.Status (or something like that) using a CollectionViewSource, you can use a Converter inside the collectionViewSource to do the grouping. Or is it a HierarchicalDataTemplate? (Or both? Sorry, very vague today). The point is, it can work very well and auto-magically (specifically tried in an IM client with instant contact searching too, heh)
Not saying this isn’t cool or that it isn’t harder to do it with “native” WPF, but it is doable. Will definitely look into SyncLinq when I have a chance!
Wow, I didn’t realise just how ‘difficult’ it could be to handle this kind of thing within a WPF/ Win Forms application (it’s been a while since I’ve done much Win Forms work).
I can really see how SyncLINQ would assist from this point of view. But how does SyncLINQ detect the text change event of the text box?
Also, how does it handle pasting into a text field? (Only wondering as coming from web pasting uses different UI events to key presses)
Hi Aaron,
SyncLINQ detects that the textBox1 expression refers to a WPF TextBox object, which is a dependency object. One of the dependency builder strategies is to find WPF dependency objects. It traces the property paths used on the textBox1 object (.Text, in this case), and looks for a matching Dependency Property. When it finds one, it hooks up for the dependency property changed event and monitors it.
This will capture programmatic changes, keyboard typing, cut and paste, or anything else you can think of.
Hi Paul,
I was preparing a sample for this which did some filtering on a double rather than a string. I found that if I used a TextBox to enter the double:
DataContext = from q in Quake.Quakes.AsBindable()
where q.Magnitude >= Double.Parse(MagnitudeBox.Text)
select q;
then Bindable LINQ handled it fine: as I typed in the text box, the set in the list box grew or shrank accordingly.
But if I used a Slider and its Value property:
DataContext = from q in Quake.Quakes.AsBindable()
where q.Magnitude >= MagnitudeSlider.Value
select q;
the dependency didn’t seem to get picked up: as I moved the slider, the list remained stuck on the original query.
Slider is a dependency object and Value is a dependency property, so I’m not sure what’s different from the text scenario. Any guesses? Am I making an obvious schoolboy error? Do I need to use a non-default dependency builder strategy?
(If you want the sample project, flick me an email.)
Oop, found the issue. Bindable LINQ seems to pick up dependencies *only if* the dependency property is defined *directly* on the dependency object type. ValueProperty is defined on RangeBase, not Slider, so Bindable LINQ doesn’t find it.
Similarly, if you create a dummy derived class of TextBox, dependency tracking for the Text property stops working.
It looks like the problem is occurring in WpfMemberTokenFactory.ParseNext, where it uses GetField() to find the dprop. Will have a go at fixing it and let you know.
Adding BindingFlags.FlattenHierarchy to the GetField() call fixes the problem.
I’m not sure how to submit patches on CodePlex, so I guess I’ll leave this with you — hope that’s okay. Sorry for the trickly comments.