2010-12-09 12 views
0

Ich versuche, das MVVM Muster für meine WP7 Silverlight App zu implementieren, und ich habe ein Problem mit dem asynchronen JSON Rest Anruf. Ich habe die folgenden zwei Methoden, die sich auf meiner WP7-Anwendungsseite befanden, in meine ViewModel-Klasse verschoben.ASync JSON REST Anruf Problem mit MVVM

public void FetchGames() 
{    

    ObservableCollection<Game> G = new ObservableCollection<Game>(); 
    //REST call in here 
    var webClient = new WebClient(); 
    Uri uri = new Uri("http://www.somewebsite.com/get/games/league/" + league); 
    webClient.OpenReadCompleted += new OpenReadCompletedEventHandler(OpenReadCompletedGames); 
    webClient.OpenReadAsync(uri); 
} 

private void OpenReadCompletedGames(object sender, OpenReadCompletedEventArgs e) 
{ 
    DataContractJsonSerializer ser = null; 
    ser = new DataContractJsonSerializer(typeof(ObservableCollection<Game>)); 
    Games = ser.ReadObject(e.Result) as ObservableCollection<Game>; 
    this.IsDataLoaded = true; 

} 

Nun ist das Problem, dass der folgende Code nicht funktioniert, da es sich um einen asynchronen Aufruf handelt. Der folgende Code befindet sich auf meiner App-Seite.

protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e) 
{ 
    base.OnNavigatedTo(e); 
    if (NavigationContext.QueryString.TryGetValue("league", out league)) 
    {    

try 
{ 
    App.gViewModel.league = league; 
    App.gViewModel.FetchGames(); 
    if(App.gViewModel.IsDataLoaded) 
    { 
    lbTeams.ItemsSource = App.gViewModel.Games; 
    }  
} 
catch() 
{     
    //error logging in here    
} 
    } 

} 

durch den Code Stepping zeigt, dass FetchGames trifft aufgerufen wird dann die nächste Zeile (if (App.gViewModel.IsDataLoaded) ) vor dem Asynchron-Anruf beendet ist. Daher ist IsDataLoaded immer falsch und ich kann die Listbox auf der Seite nicht binden.

Viel googeln Ich habe einige mögliche Lösungen, aber ich kann sie nicht zu meinem speziellen Problem konvertieren. Man ist so und es hat mit Fortsetzungsstil zu tun. Ich konnte es nicht zur Arbeit bringen und würde mich über Hilfe freuen.

Danke!

void DoSomethingAsync(Action<string> callback) { 
    HttpWebRequest req; // TODO: build your request 

    req.BeginGetResponse(result => { 
     // This anonymous function is a closure and has access 
     // to the containing (or enclosing) function. 
     var response = req.EndGetResponse(result); 

     // Get the result string and call the callback 
     string resultString = null; // TODO: read from the stream 

     callback(resultString); 
    }, null); 
} 

Antwort

3

Dies kann durch Verschieben

lbTeams.ItemsSource = App.gViewModel.Games; 

bis zum Ende des OpenReadCompletedGames Verfahren gelöst werden. Sie müssen den Dispatcher verwenden, um die Benutzeroberfläche von hier aus zu aktualisieren.

Dispatcher.BeginInvoke(() => { lbTeams.ItemsSource = App.gViewModel.Games; }); 
+0

@Mick Sie schlagen mich diesmal, o) –

+0

@Mick Vielen Dank für die Antwort. Wenn ich Ihren Code in die OpenReadCompletedGames-Methode einfüge, erhalte ich folgende Fehlermeldung: Fehler Kann Lambda-Ausdruck nicht in Typ 'System.Delegate' konvertieren, da es kein Delegattyp – sleeprince

+0

ist, der einen Cast zur Aktion hinzufügen sollte: Dispatcher.BeginInvoke (** (Aktion) (**() => {lbTeams.ItemsSource = App.gViewModel.Games;} **) **); –