2015-03-03 82 views
2

我想解析這個JSON對象並將其綁定到Xamarin.Forms中的ListView。Xamarin.Forms JSON對象到列表視圖

我完全失去了如何處理它,因爲我對Xamarin Forms完全陌生。

有沒有更簡單的方法來做到這一點?

我返回的JSON對象

[ 
    { 
    "id": 1, 
    "name": "Leanne Graham", 
    "username": "Bret" 
    }, 
    { 
    "id": 2, 
    "name": "Ervin Howell", 
    "username": "Antonette" 
    } 
] 

這裏是我的代碼來處理餘下的JSON響應

public class RestClient 
    { 
     public RestClient() 
     { 
     } 

     public async Task<User[]> GetUsersAsync() { 

      var client = new System.Net.Http.HttpClient(); 

      client.BaseAddress = new Uri("http://jsonplaceholder.typicode.com"); 

      var response = client.GetAsync("users"); 

      var usersJson = response.Result.Content.ReadAsStringAsync().Result; 

      var rootobject = JsonConvert.DeserializeObject<Rootobject>(usersJson); 

      return rootobject.Users; 

     } 
    } 

Users.cs

public class Rootobject 
     { 
      public User[] Users { get; set; } 
     } 

     public class User 
     { 
      public string id { get; set; } 
      public string username { get; set; } 
     } 

ListView Form Code 
var sv = new RestClient(); 
      var es = sv.GetUsersAsync(); 
      Xamarin.Forms.Device.BeginInvokeOnMainThread (() => { 
       Debug.WriteLine("Found " + es.Result.Length + " users"); 
       listView.ItemsSource = es.Result; 
      }); 

XAML

public ListViewPage() 
     { 
      Title = "Users"; 

      var sv = new RestClient(); 
      var es = sv.GetUsersAsync(); 
      Xamarin.Forms.Device.BeginInvokeOnMainThread (() => { 
       Debug.WriteLine("Found " + es.Result.Length + " users"); 
       listView.ItemsSource = es.Result; 
      }); 


      listView = new ListView(); 
      listView.ItemTemplate = new DataTemplate(typeof(TextCell)); 
      listView.ItemTemplate.SetBinding(TextCell.TextProperty, "username"); 

      listView.ItemTemplate = new DataTemplate(typeof(ItemCell)); 

      Content = new StackLayout { 
       Children = { 
        listView 
       } 
      }; 
     } 

回答

3

您的異步調用不正確。如果你必須在構造函數中完成它(這不是最好的地方),你應該使用ContinueWith作爲使用Task.Result不應該被使用。此外,因爲結果是一個阻塞調用,所以在構造列表視圖之前分配項目源,並且獲得空引用異常。

試試這個:

public class ListViewPage : ContentPage 
{ 
    private readonly ListView listView; 

    public ListViewPage() 
    { 
     Title = "Users"; 

     this.listView = new ListView {ItemTemplate = new DataTemplate(typeof (TextCell))}; 
     this.listView.ItemTemplate.SetBinding(TextCell.TextProperty, "username"); 

     Content = new StackLayout 
     { 
      Children = { this.listView } 
     }; 

     var sv = new RestClient(); 
     var es = sv.GetUsersAsync().ContinueWith(t => 
     { 
      if (t.Status == TaskStatus.RanToCompletion) 
      { 
       Debug.WriteLine("Found {0} users.", t.Result.Length); 
       Device.BeginInvokeOnMainThread(() => this.listView.ItemsSource = t.Result); 
      } 
     }); 
    } 
} 

稍微更好的選擇(但也不是完美的),將覆蓋出現的方法和標誌是異步。這樣,您可以使用異步REST調用方法的await。請注意,除非添加附加代碼,否則每次顯示視圖時都會調用此方法。

protected override async void OnAppearing() 
    { 
     base.OnAppearing(); 

     try 
     { 
      var sv = new RestClient(); 
      // activate/show spinner here 
      this.listView.ItemsSource = await sv.GetUsersAsync(); 
      // inactivate/hide spinner here 
     } 
     catch (Exception exception) 
     { 
      this.DisplayAlert("Error", exception.Message, "OK"); 
     } 
    } 
+0

我應該如何實現一個進度微調(思考微調),以便視圖加載速度快,只顯示微調,直到它已經加載了JSON? – dasmikko 2015-03-04 09:00:25

+0

我編輯了OnAppearing重載,以顯示您將顯示/隱藏微調器的位置。以下是該指標的API:http://iosapi.xamarin.com/?link=T%3aXamarin.Forms.ActivityIndi​​cator – SKall 2015-03-04 14:55:07

+0

感謝您的幫助! – dasmikko 2015-03-04 14:57:30

0

看起來你不是在等待sv.GetUsersAsync,我不確定Result是否包含所有數據而不等待操作完成。

儘管可以使用任何集合和任何對象作爲列表視圖的數據源,但最好使用ObservableCollection並使User類實現INotifyPropertyChanged(看看Fody.PropertyChanged nuget包)。

你能和我們分享xaml嗎?

編輯1

您可以定義您的ItemTemplate兩次。

listView.ItemTemplate = new DataTemplate(typeof(TextCell)); //first definition 
listView.ItemTemplate.SetBinding(TextCell.TextProperty, "username"); 

listView.ItemTemplate = new DataTemplate(typeof(ItemCell)); //second definition, remove it 

加上它是更好地使用MVVM與Xamarin.Forms和視圖模型加載數據,而不是在你的頁面的構造函數。 Here是關於mvvm和Xamarin.Forms中的數據加載的好文章。

EDIT 2

爲什麼使用異步/地等待着這樣一個奇怪的方式?而不是閱讀Task.Result屬性,最好使用async/await對。 Example

+0

現在已經添加了XAML。但我很想知道是否有更簡單的方法來加載JSON並將其綁定到我的ListView – dasmikko 2015-03-03 11:31:32

+0

編輯我的答案。你的代碼有錯誤。 – 2015-03-03 11:37:15

+0

添加了有關異步/等待的評論。對不起,如果這只是你的使用風格。 – 2015-03-03 11:45:12