Question

I'm currently developing a Windows Phone 8 app that requires the use of a web API. When I decided to move towards the MVVM model I moved the necessary code to download data from the web API over to a separate class. After implementing all necessary functionality, I realized that the thread wouldn't wait for the data to finish downloading (or at least wouldn't wait for the necessary code to run following that), the thread would go through the ViewModel constructor and return a blank list to bind to my LongListSelector control. When debugging I realized that the thread would actually go through the DownloadCompleted method within my ViewModel at some point, but it was always after the ItemsSource for my LongListSelector was already set to a blank List. In the end I did get a properly populated list of data, it's just that the LongListSelector would have already been bound to the empty List instead. Is there anyway I can change what I'm doing so that my LongListSelector actually binds to the real data I'm getting from the web instead of binding to an empty List before it's properly populated with data? Whether it's somehow waiting for all the necessary code to run before the thread moves on, or updating the View when my List gets properly populated with data, I'm willing to accept any sorts of suggestions as long as they get my code to finally work.

Thanks in advance!

In MainPage.xaml.cs:

    public void Retrieve()
    {
        MySets.ItemsSource = new MySetsViewModel(CurrentLogin).BindingList;         
    }

MySetsView Model is defined as the following:

public class MySetsViewModel
{
    User CurrentLogin;
    List<Sets> SetsList;
    public List<Sets> BindingList { get; set; }

    public MySetsViewModel(User CurrentLogin)
    {
        this.CurrentLogin = CurrentLogin;
        Retrieve(CurrentLogin);
    }

    public async void Retrieve(User CurrentLogin)
    {
        if (IsolatedStorageSettings.ApplicationSettings.Contains("AccessToken"))
        {
            CurrentLogin.AccessToken = IsolatedStorageSettings.ApplicationSettings["AccessToken"].ToString();
        }
        if (IsolatedStorageSettings.ApplicationSettings.Contains("UserID"))
        {
            CurrentLogin.UserId = IsolatedStorageSettings.ApplicationSettings["UserID"].ToString();
        }

        try
        {
            HttpClient client = new HttpClient();
            HttpRequestMessage request = new HttpRequestMessage();
            client.DefaultRequestHeaders.Add("Authorization", "Bearer " + CurrentLogin.AccessToken);
            client.DefaultRequestHeaders.Add("Host", "api.quizlet.com");
            var result = await client.GetAsync(new Uri("https://api.quizlet.com/2.0/users/" + CurrentLogin.UserId + "/sets"), HttpCompletionOption.ResponseContentRead);
            string jsonstring = await result.Content.ReadAsStringAsync();
            DownloadCompleted(jsonstring);
        }
        catch
        {

        }


    }

    void DownloadCompleted(string response)
    {
        try
        {
            //Deserialize JSON into a List called Sets
            this.BindingList = Sets;

        }
        catch
        {

        }
    }

}
Was it helpful?

Solution

All you have to do is implement INotifyPropertyChanged on your view model. Raise the PropertyChanged event inside the setter for "BindingList", and the view will update itself.

public class MySetsViewModel : INotifyPropertyChanged
{
    public List<Sets> BindingList 
    { 
        get { return _bindingList; }
        set
        {
            _bindingList = value;
            RaisePropertyChanged("BindingList");
        }
    }
    private List<Sets> _bindingList;

    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void RaisePropertyChanged(string propertyName)
    {
        var handler = PropertyChanged;
        if (handler != null)
            handler(this, new PropertyChangedEventArgs(propertyName));
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top