Bxf updating view on async data method question

Feb 23, 2011 at 1:52 PM

Ok, so I'm progressing in my understanding of Bxf and its benefits.  Though I do have a new MVVM/Bxf question, which may actually be more WCF/XAML related but I figured this would be a good place to start.

The issue I'm running into is updating my ViewModel on an Async data call.

The goal is to load a form with several text fields, unpopulated but still bound to the model and one data grid, also bound to the model.  However, the data grid needs to display information gathered through a WCF Data Services call to my database, returning a list of text values.  To accomplish this, in the constructor of the ViewModel class, I am making my call to the WCF Service and then populating the Model value that contains the list of items in a resulting Lambda expression.  However, by the time the async call returns my code has already bound the view to the view model.  As a result, when the async call returns with my data, I am not able to link it up from the object to the view.  If I take out the async call and create a manual test record for the data grid in the constructor it shows up as it should in the view so I am confident the issue is somewhere in syncing everything together on the return async call.

My WCF Data services call:

                var courses = svcContext.BeginExecute<BaselineService.Organizations>(
                    new Uri(string.Format("{0}GetOrganizationsPerEmailAddress?email='{1}'", svcContext.BaseUri, "user@email.com"),
                            UriKind.RelativeOrAbsolute),
                            (asResult) =>
                            {
                                //Dispatch the EndExecute call to the UI thread
                                System.Windows.Deployment.Current.Dispatcher.BeginInvoke(
                                 () =>
                                 {
                                     DataServiceQuery<BaselineService.Organizations> query = (DataServiceQuery<BaselineService.Organizations>)asResult.AsyncState;
                                     theList = svcContext.EndExecute<BaselineService.Organizations>(asResult).ToList();
                                     _model.Organizations = theList;
                                 }
                                 );
                            }
                            , null);

I connect the returned data to my model with _model.Organizations.  Organizations is defined in my model as: public List<Organizations> Organizations {get; set;}

The type Organizations is from my entity data model.

Again, the view is synced with the model if I manually create an Organizations item in the constructor outside of the async data call but will not sync upon returning from the async WCF data call.  I researched the DataRefresh(Model) method but this appears to be specific to CSLA and I am not using it (just Bxf).

Suggestions?

Thanks.

Coordinator
Feb 23, 2011 at 2:31 PM

I generally let data binding do the work for me as much as possible.

If I have some data loading async, I'll bind the view to a viewmodel property that will have the data. When the data arrives, that viewmodel property is set to the new value (the new model that actually has data) and that causes a PropertyChanged event and the UI updates automatically.

The one common issue with this is where multiple model objects are bound to the same view, with interdependent bindings. For example, a combobox needs to have its data before the business object can bind its key property to the combobox's key.

There's a concept called a unit of work object that is heavily used in CSLA, but is a broader design pattern you can use anywhere. Basically, create a "data ferry" object that asynchronously gets the business object and the list object needed to populate the combobox control. When that async call returns, you know you have both objects at the same time, so you can set the viewmodel's DataList property first (thus populating the combobox), and then the BusinessModel property (thus binding the rest of the UI fields to the business object's properties).

I'm not saying you have to use CSLA. I'm saying that some of the concepts and design patterns used by CSLA are things I'm using because they work. But they are design patterns and coding practices you can (and need to) write to work in this async world.

Feb 23, 2011 at 5:08 PM

Thanks for your response and for working with this newbie to the world of async silverlight MVVM development as I ever so slowly climb the learning curve.

Where my confusion is at present is the returned data from the async call.  Keeping things simple for now let's just use a textbox example.  On this XAML form (view), I have a text box bound to a parameter in my view model.  When I load my view model's constructor, I set a value for this parameter.  In stepping through the debugger, I see the parameter updating (through the set operation), the OnPropertyChange() fire ad the field on the view display the correct information.

However, if I put that exact same line of code, that works in the constructor, in the Lambda expression as shown above, also in the constructor, I see the model parameter update but the OnPropertyChange() method does not fire and the field is not updated in the view.    My understanding is that the return of the async call is on a different thread from the UI and that's why the OnPropertyChange() method does not fire.  Am I correct?  If so, how do I update the UI thread that, I assume, will also call OnPropertyChange() and thus update the view?  Would I need a data ferry, as you call it, for something this simple as well?

Feb 23, 2011 at 6:56 PM

Ah ha!

I accomplished what I was trying to accomplish.  Simple error on my part.  In the Lambda expression, I was making reference directly to the model parameter (_model.paramater).  The fix was to instead make reference to the ViewModel parameter which in turn updated the Model paramater and called OnPropertyChanged().  Quite simple error really in looking at it.

On to the next step on the learning curve.