This may not be related to CSLA, but I wanted to ask here anyway just in case. In my WinRT app, when I navigate to another page from the main page, I have the following code in the LoadState event:
ViewModels.MyViewModel vm = new ViewModels.MyViewModel();
this.DataContext = vm;
In the constructor of MyViewModel is the following:
EditableRoot.NewEditableRoot((o, e) =>
{
if (e.Error != null)
throw e.Error;
else
Model = e.Object;
});
And in the EditableRoot CSLA object, I have the following method:
public static void NewEditableRoot(EventHandler<DataPortalResult<EditableRoot>> callback)
{
DataPortal.BeginCreate<EditableRoot>(callback);
}
What I would expect is that, because the NewEditableRoot factory method is being called asynchronously, there should be no lag in the WinRT app's ability to display the page to which I'm navigating. But that isn't the case. The app pauses like it is trying to create the object, and after about 1 second it then displays the new page. If I remove the call to EditableRoot.NewEditableRoot() within the VM constructor, the page loads immediately. The new object being created doesn't even do a lot and is marked with [RunLocal]. Regardless, though, shouldn't the WinRT page simply load up fast since the object creation isn't taking place in the UI thread?
I'd appreciate any pointers on what to look for. But in the meantime, to get around this I have used a DispatcherTimer in the page being loaded. The interval is set to 1/2 second, at which point it calls a public method on the VM to do the creation of the object, following which I rebind the VM to the page's data context. Very ugly, but it does give the intended effect...the page loads quickly.
I have had difficulties with initializing the model in the constructor, though in your code I'd expect it to work.
But you can't mark a constructor as async, so you can't use await there. Because of this, the 4.5 ViewModelBase now includes an InitAsync method so you can do this in your UI code:
this.DataContext = await new MyViewModel().InitAsync();
Then in the viewmodel class you don't implement a constructor, or at least not one that starts any async work. Instead you override another method:
protected override async Task<T> DoInitAsync()
{
return await MyBusinessClass.GetMyBusinessClassAsync();
}
This has been working well for me, and I think you could do the equivalent with the older event style async methods as well.
Thanks. So does the concept of BeginRefresh in the VM not play a role anymore? Since BeginRefresh doesn't return anything, what would I be returning in the DoInitAynsc?
Or should I not use BeginRefresh and instead do as you did going forward...just calling the static factory method in the business object? (e.g. MyBusinessClass.GetMyBusinessClassAsync() )
I changed my object to use the newer async style, and used the InitAsync call when setting the DataContext, as you show above. But it still does the same thing...the initial view hangs for about 1.5 seconds and then displays the new view. I'm probably doing something wrong somewhere else. It seems as if I have three options:
I'm leaning toward #1 because at least that way I can display a progress bar to let the user know something is happening.
Try breaking the line of code in two:
var vm = new ViewModel();
this.DataContext = await vm.InitAsync();
Also, it might be that you are putting this code in a blocking method/event. I typically put this code in the launching event handler, which of course must be decorated with the async keyword.
Thanks for your continued help. I tried that, but no change, unfortunately. As to where I have it, I'm calling this in the LoadState event of the second view (the one being navigated to). I added "async" to it...assuming that is acceptable.
protected override async void LoadState(Object navigationParameter, Dictionary<String, Object> pageState)
Copyright (c) Marimer LLC