Reputation: 6458
I have a windows phone (wp8) app using MVVM pattern which contains a view with a pivot control and is binded to a ViewModel (PivotMainViewModel).
Each pivot item contains a different view (datatemplate) and is binded to its own viewmodel (PivotItemViewModel1, PivotItemViewModel1, etc...) and all of this is working well.
My PivotMainViewModel is initialized via xaml binding but as it needs a parameter, it is also "initialized" via the OnNavigatedTo event of the view.
PivotItemViewModel4 pivotItemViewModel4 = Resources["PivotItemViewModel4"] as PivotItemViewModel4;
if (selectedRow.Id > 0)
{
pivotItemViewModel4.InitializeDocumentDetails(selectedRow);
}
but I'm not sure about how to deal with the web service requests which I want to make asynchronously. I need to make a web service request for each individual pivot item "view" and load data the minute it is returned but I need to do this as soon as the pivot is initialized but I'm not sure about the following:
I need to fill data in each of the pivot item "views" and therefore their relevant viewmodels but I'm not sure whether I should make all the asynchronous call from PivotMainViewModel or from each individual viewmodel defined for each of the pivot item.
Whether I call this from the PivotMainViewModel or I call this from each of the pivot item viewmodel, when should I call this?
Should I call this from the constructor:
public PivotItemViewModel1
{
this.Document = GetDocument();
}
or the Get part of my property when its internal variable is null for example? i.e.
public Document Document
{
get { return this._document ?? GetDocument(); }
}
or other?
If I'm supposed to call this from the constructor of the individual viewmodel, how do I do this? I can't use async on a constructor nor can I set async on a property.
What is the best way to make an async call to a web service when dealing with MVVM.
Again, I'm not sure which is best:
4.1 Display a progress bar of some sort, request all 4 requests and wait for all of them to complete and then hide a progress bar
4.2 Display a progress bar of some sort within each individual views and hide them accordingly as each request gets completed
Last problem... Hanging. I've ready numerous articles on the async and hanging but they always describe the problem when dealing with a click event, but I don't understand how to deal with this when you don't have a click event but when you want to call this when a viewmodel is initialized. If you know how, can you please explain and provide a simple example.
Upvotes: 1
Views: 525
Reputation: 102743
There are different concerns to keep in mind:
So, the question of:
presents a trade-off between #2 and #3. It's really a judgement call, depending on what kind of feel you want the app to have.
I'm not sure whether I should make all the asynchronous call from PivotMainViewModel or from each individual viewmodel defined for each of the pivot item
I do think that #1 above implies the latter -- each view model should own its own data if possible, for the sake of encapsulation.
Edit To use async on a property, you have to use the setter, not the getter. Hook to the view-model's "initialize" event (or similar):
public Document Document
{
get { return this._document; }
set
{
if (this._document == value)
return;
this._document = value;
RaisePropertyChanged("Document");
}
}
public async Task<Document> GetDocument
{
// ...
}
private async Task LoadData()
{
Document = GetDocument();
}
public void Initialize()
{
LoadData();
}
Upvotes: 2