I'm building an application which uses a plug-in architecture to access specific devices. These devices have fields, which I named Attributes, that can be read, written or both. This is done using a WPF front-end running in it's own thread and a MVVM like structure in the back end which wraps specific plug-in to expose it's attributes in a generic way.

Some details about the threading structure

I have two "host" objects, one initiates the plug-in structures eventually exposes two views: a view of available plug ins and (if a plug-in was selected) a view of all attributes known by a single plug-in. The other eventually starts a STA-thread and runs the a main window in a WPF application. The second host uses BackgroundWorkers to do select, initialization, update and submit tasks. The DoWork events/delegates(I believe they are called delegates) are defined in a ViewController class which is in the MVVM structure and provides a functional interface for updating etc. and implements the INotifyPropertyChanged interface.

Some more details

Upon creation of the mainwindow it's context is set to the view controller object. The GUI then binds two list boxes to both views.

The problem

When I call the selectPlugin method from within the UI thread it freezes until the connect operation is complete and every single attribute is loaded into the list contained by the ViewModel. However it does work and afterwards the ListBox itemssource binding is updated and all attributes are shown.

However I don't want the UI to freeze up on every operation, so I implemented backgroundworkers. It all works fine, the objects get updated and the binding source is replaced by a new View instance. But the binding itself doesn't update.

I tried allot off different solutions using the Dispatcher.Invoke or the DoWorkComplete event in the UI thread. I found that the PropertyChanged event itself stays null using the following property setter:

The PropertyChanged event as declared above is always null. This could or should have something to do with the actual binding in XAML, however i did set de datacontext of the main window in the UI thread like this:

I use a Singleton instance off the UI host object, in case that makes a difference.

In XAML I use a custom dependency property on a UserControll containing the AttributesListbox and some styling code. The actual ListBox binds to this property for it's own ItemSource property. Don't think this should be different from using the list box directly, but just in case this causes the issue with the PropertyChanged event being null, and is implemented in the following way:

What is wrong with the way I use the ViewController object in conjunction with the UI? And thus why is the PropertyChanged event always null? This should mean I messed up the binding process somewhere doesn't it?

The second question(s)

How do I get the OnPropertyChanged event to notify the UI thread, specificity the Binding in the UserControll(AttributesListbox)?

What route does the event follow?

for instance:
I use a DoWork delegate and this method changes the property directly from within the instance, which is not in the UI thread. Does this cause the event never to reach the UI thread because is it raised in the other worker thread?

I can't get my head around the event bubbling/tunnelling, is a event restricted to the thread which created the instance or the thread which called the specific method(using a dispatcher or whatever)?

Hypothesis

I suspect there are two issues in my case:
1. The PropertyChanged handler stays null because the object is either not bound or because it is not created in the correct thread.
2. The event, if it where actually fired, never reaches the correct thread because it gets stuck in either the BackgroundWorker thread or the back end "host" thread.

This is the first question I have asked here, so if your missing some pieces off the puzzle please do inform me.

Thanks for taking the time to read about my little problem situation, I hope we can come to a solution.

2 Answers
2

I think you may have messed up the binding of your listbox, namely (shortened for simplicity):

<ListBox ItemsSource="{Binding Source}" />

this binding means "look for a property called Source in the my current DataContext", which I suspect is not what you intend. If you want to bind to the property Source of the AttributesListBox (which I suppose hosts the above listbox), you should do it this way:

which means - "look for a property called Source in the first object up the tree that is of type AttributesListBox". Of cource you still have to bind that Source property to the correct thing of your controller, but I suppose you have done that.

The deal with the property changed event is that it must be raised from the UI (Dispatcher) thread, if you raise it from a background thread wpf will not automatically marshal it to the UI thread. So make sure that when the background work has completed, you set the propoperties which need to be updated on the UI thread.

Thanks for your response. The code seems to work with just {Binding Source} but this might be a coincidence, I can see how your binding expression is a safer bet. And the PropertyChanged event seems to somehow, maybe coincidental, make it's way to the UI thread. I don't use the Dispatcher or the DoWorkComplete event to make sure the property is updated using the UI thread. Is this a safe bet or does this deserve a good look? However you did clarify my second question(s).
–
Sander AernoutsDec 22 '10 at 12:55

Well I am surprised that the {Binding Source} works, what is the DataContext of the ListBox at runtime (you can check it with the "snoop" tool found on codeplex)? About the INotifyPropertyChanged, I was wrong, and I learned something new today =) Check this stackoverflow.com/questions/2553333/…
–
xenryDec 22 '10 at 13:55

The great thing about asking a question is that is forces you to really think on de cause off your problem, thus taking a little break you might finally, after two days, find the utterly simple solution.

The problem was a ParameterizedThreadStart which request a void method(object arg) so the compiler does no type checking what so ever as long as you pass a object. An I passed the wrong object because I edited the method. The safe typecasting using the "as" operator seems to be a pain to, it seems to swallow an CastingException thus not informing you about the small mistake.