Asynchronously loading Blendable sample data in MVVM Light in the view model's constructor
Asked Answered
F

1

1

I have a Windows Phone 8.1 MVVM Light project and I am struggling to keep it Blendable.

As I see it I have a few options. I can load different view models depending on whether ViewModelBase.IsInDesignModeStatic is true in the ViewModelLocator constructor, or I can test ViewModelBase.IsInDesignModeStatic in the view model constructor and load data appropriately.

If ViewModelBase.IsInDesignModeStatic is true I need to load data from file. Here's my code:

public async Task<ThingsSampleDataSource> GetSampleDataAsync()
{
    if (_DeserializedThingsSampleDataSource == null)
    {
        var dataUri = new Uri(_SampleDataJSONFile);
        var file = await StorageFile.GetFileFromApplicationUriAsync(dataUri);
        var jsonText = await FileIO.ReadTextAsync(file);
        _DeserializedThingsSampleDataSource = JsonConvert.DeserializeObject<ThingsSampleDataSource>(jsonText);
    }
    return _DeserializedThingsSampleDataSource;
}

When I call that method I need to mark the call await and thus the calling method async. But constructors cannot be marked async.

Or I can provide a ContinueWith continuation instead of awaiting return of the asynchronous code. But Blend loads the page before the ContinueWith is complete.

Given that sample data is loaded in the view model or the locator service constructors and it has to load data from a file, an asynchronous activity, how do I do this in MVVM Light so that the sample data is available in Blend?

(N.B. other answers I have found, for example this one, do not use MVVM Light.)

Fricke answered 9/6, 2015 at 10:54 Comment(3)
Not sure about blend, but maybe you can use this approach: #30303720Owe
I cannot see how to apply that approach to this problem - can you be more specific?Fricke
I've submitted this as an issue too.Fricke
O
1

Load your data on the page load event, using a Command, so you can take advantage of the await/async stuff. I don't know how this works with blend as I don't use it much.

View:

<i:Interaction.Triggers>
    <i:EventTrigger EventName="Loaded">
        <i:InvokeCommandAction Command="{Binding PageLoadedCommand}"/>
    </i:EventTrigger>   
</i:Interaction.Triggers>

ViewModel:

public RelayCommand PageLoadedCommand { get; private set; }
public MyConstructor(IService serviceInjected)
{
    PageLoadedCommand = new RelayCommand(async()=>await OnPageLoaded());
....
}

private async Task OnPageLoaded()
{
   if(ViewModelBase.IsInDesignModeStatic)
   {
       var data = await GetSampleDataAsync();
       //Do something..
   }
}
Owe answered 9/6, 2015 at 11:42 Comment(3)
Loading a page in Blend does not call the page load event, which is what my question is about. My code works fine outside blend, but as I say in the question "I am struggling to keep it Blendable". I'll edit the question to make that more obviousFricke
I see now.. I'd try with some TPL Task.ContinueWith then.Owe
That's what I have, but the data is not making it into Blend (I guess it's loading before the ContinueWith but I'm not sure)Fricke

© 2022 - 2024 — McMap. All rights reserved.