2017-01-14 6 views
0

私の.Net Mvvm/MVC学習旅行で私は別の問題を見つけました。c#Mvvm GETリクエストのデータでObservableObjectプロパティを埋めてください。

ObservableObjectプロパティを塗りつぶして、ウィンドウまたはユーザーコントロールにバインドできるようにしています。このプロパティは、GET要求を実行するprivate async voidの内部に埋め込まれます。

awaitメソッド内のメソッド/関数をプロパティ内で使用できないため、メソッド内のプロパティを埋めようとしました。常にNullReferenceExceptionを与えています。 改行を設定し、F11(ステップオーバー)を何度も押すと、目的のプロパティEventsを除いて、すべてが正しく満たされていることがわかりました。

の流れはこのようなものです:

  1. あなたは国を選択 - >のSelectedItemはSelectedCountry
  2. にバインドされている "地域" を選択 - >のSelectedItemはSelectedProvince
  3. にバインドされている都市を選択 - > selectedItemはSelectedCityにバインドされています

上記の各プロパティは、自分のAPIであるAPI i私のデータベースからデータを取り出し、それを表示/返すためのものです。 ObservableObjectのプロパティ "Country、Province、City"は、APIと通信するこれらのメソッド内で設定されます。この時点ですべてがまだうまく動作します。

Cityプロパティが設定されている場合、別のObservableObjectプロパティOrgsを満たすメソッドGetOrgsByCity()が呼び出されます。 Orgsのセッターでは、GetFacebookData(FB_IDS)が呼び出されます。このメソッドには、型がList<string>であり、LINQによってfilterdリストを返すプロパティが必要です。すべてはまだうまく動作しています。この方法は、FacebookのにGETリクエストを実行し、GetFacebookData(FB_IDS)方法で

私はEventsという名前ObservableObjectプロパティを埋めるためにしようとしている:

は、ここで問題にしています。 IsSuccessStatusCodetrueとなり、ObservableObjectプロパティEventsを除いてすべてが正しく塗りつぶされます。

foreachの結果リスト(List<FB> data)を「変換」してEventsを入力します。私はそれを実行すると、それはNullReferenceExceptionをスローする破る。 Eventsは、他の変数が正しく入力されているため、nullまたは何かと言います。

Eventsプロパティを記入しようとすると、NullReferenceExceptionのプロパティが表示される理由はありますか?

XAML(それがバインドされています場所):

<Grid Grid.Row="0" DataContext="{Binding Source={StaticResource PartOneVM}}"> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="30px" /> 
      <RowDefinition Height="30px" /> 
     </Grid.RowDefinitions> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition Width="1*" /> 
      <ColumnDefinition Width="1*" /> 
      <ColumnDefinition Width="1*" /> 
     </Grid.ColumnDefinitions> 

     <TextBlock x:Name="txbCountry" Style="{StaticResource InfoLabelCountry}" /> 
     <ComboBox x:Name="cboCountry" Style="{StaticResource CountryBox}" ItemsSource="{Binding Countries}" DisplayMemberPath="En_name" SelectedItem="{Binding SelectedCountry}" /> 
     <TextBlock x:Name="txbGewest" Style="{StaticResource InfoLabelGewest}" /> 
     <ComboBox x:Name="cboGewest" Style="{StaticResource GewestBox}" ItemsSource="{Binding Provinces}" DisplayMemberPath="Name" SelectedItem="{Binding SelectedProvince}" /> 
     <TextBlock x:Name="txbCity" Style="{StaticResource InfoLabelCity}" /> 
     <ComboBox x:Name="cboCity" Style="{StaticResource CityBox}" ItemsSource="{Binding Cities}" DisplayMemberPath="Name" SelectedItem="{Binding SelectedCity}" /> 
    </Grid> 
    <Grid Grid.Row="1"> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="1*"></RowDefinition> 
     </Grid.RowDefinitions> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition Width="1*"></ColumnDefinition> 
     </Grid.ColumnDefinitions> 
     <ListBox Height="300px" Grid.Row="0" Grid.Column="0" ItemsSource="{Binding Events}"> 

     </ListBox> 
    </Grid> 

のViewModel 問題は下にここに起こる:

public class PartOneVM : ObservableObject, IPage 
{ 
    #region props 
    public string Name { get { return "Page One"; } } 

    private ObservableCollection<Country> _countries; 

    public ObservableCollection<Country> Countries 
    { 
     get { return _countries; } 
     set { _countries = value; OnPropertyChanged("Countries"); } 
    } 
    private ObservableCollection<Province> _provinces; 

    public ObservableCollection<Province> Provinces 
    { 
     get { return _provinces; } 
     set { _provinces = value; OnPropertyChanged("Provinces"); } 
    } 
    private ObservableCollection<City> _cities; 

    public ObservableCollection<City> Cities 
    { 
     get { return _cities; } 
     set { _cities = value; OnPropertyChanged("Cities"); } 
    } 
    private Country _selectedCountry; 

    public Country SelectedCountry 
    { 
     get { return _selectedCountry; } 
     set { _selectedCountry = value; GetProvincesByCountry(); OnPropertyChanged("SelectedCountry"); } 
    } 
    private Province _selectedProvince; 

    public Province SelectedProvince 
    { 
     get { return _selectedProvince; } 
     set { _selectedProvince = value; GetCitiesByProvince(); OnPropertyChanged("SelectedProvince"); } 
    } 
    private City _selectedCity; 

    public City SelectedCity 
    { 
     get { return _selectedCity; } 
     set { _selectedCity = value; GetOrgsByCity(); OnPropertyChanged("SelectedCity"); } 
    } 
    private ObservableCollection<Org> _orgs; 

    public ObservableCollection<Org> Orgs 
    { 
     get { return _orgs; } 
     set { _orgs = value; GetFacebookData(FB_IDS); OnPropertyChanged("Orgs"); } 
    } 
    public List<string> FB_IDS 
    { 
     get { if (Orgs == null) return null; return (from s in Orgs where s.CityID.Equals(SelectedCity.ID) select s.FB_ID).Distinct().ToList<string>(); } 
    } 
    private ObservableCollection<FB> _events; 
    public ObservableCollection<FB> Events 
    { 
     get { return _events; } 
     set { _events = value; OnPropertyChanged("Events"); } 
    } 
    #endregion 

    #region ctor 
    public PartOneVM() 
    { 
     GetCountries(); 
    } 
    #endregion 

    #region methodes 
    private async void GetCountries() 
    { 
     using (HttpClient client = new HttpClient()) 
     { 
      HttpResponseMessage response = await client.GetAsync("http://localhost:58564/api/country"); 
      if (response.IsSuccessStatusCode) 
      { 
       string json = await response.Content.ReadAsStringAsync(); 
       Countries = JsonConvert.DeserializeObject<ObservableCollection<Country>>(json); 
      } 
     } 
    } 
    private async void GetProvincesByCountry() 
    { 
     if (SelectedCountry != null) 
     { 
      using (HttpClient client = new HttpClient()) 
      { 
       HttpResponseMessage response = await client.GetAsync("http://localhost:58564/api/province/GetProvincesByCountry/" + SelectedCountry.ID); 
       if (response.IsSuccessStatusCode) 
       { 
        string json = await response.Content.ReadAsStringAsync(); 
        Provinces = JsonConvert.DeserializeObject<ObservableCollection<Province>>(json); 
       } 
      } 
     } 
    } 
    private async void GetCitiesByProvince() 
    { 
     if (SelectedCountry != null && SelectedProvince != null) 
     { 
      using (HttpClient client = new HttpClient()) 
      { 
       HttpResponseMessage response = await client.GetAsync("http://localhost:58564/api/city/GetCitiesByProvince/" + SelectedCountry.ID + "/" + SelectedProvince.ID); 
       if (response.IsSuccessStatusCode) 
       { 
        string json = await response.Content.ReadAsStringAsync(); 
        Cities = JsonConvert.DeserializeObject<ObservableCollection<City>>(json); 
       } 
      } 
     } 
    } 
    private async void GetOrgsByCity() 
    { 
     if (SelectedCountry != null && SelectedProvince != null && SelectedCity != null) 
     { 
      using (HttpClient client = new HttpClient()) 
      { 
       HttpResponseMessage response = await client.GetAsync("http://localhost:58564/api/org/GetOrgsByCity/" + SelectedCountry.ID + "/" + SelectedProvince.ID + "/" + SelectedCity.ID); 
       if (response.IsSuccessStatusCode) 
       { 
        string json = await response.Content.ReadAsStringAsync(); 
        Orgs = JsonConvert.DeserializeObject<ObservableCollection<Org>>(json); 
       } 
      } 
     } 
    } 
    private async void GetFacebookData(List<string> fb_ids) 
    { 
     var l = fb_ids 
     .Select((x, i) => new { Index = i, Value = x }) 
     .GroupBy(x => x.Index/50) 
     .Select(x => x.Select(v => v.Value).ToList()) 
     .ToList(); 

     for (var i = 0; i < l.Count; i++) 
     { 
      string ids = string.Join(",", l[i]); 
      using (HttpClient client = new HttpClient()) 
      { 
       client.BaseAddress = new Uri(@"https://graph.facebook.com/v2.8/"); 
       HttpResponseMessage response = await client.GetAsync("?ids=" + ids + "&fields=id,name,events.limit(60)&access_token=<acces_token>"); 
       if (response.IsSuccessStatusCode) 
       { 
        string json = await response.Content.ReadAsStringAsync(); 
        var result = JsonConvert.DeserializeObject<IDictionary<string, FB>>(json); 
        List<FB> data = result.Select(item => item.Value).ToList(); 

        if (data != null) 
        { 
         foreach (FB item in data) 
         { 
          if (item != null) 
          { 
           Events.Add(item); // THROWS NullReferenceException !!! 
          } 
         } 
        } 
       } 
       else 
       { 
       // error handling 
       } 
      } 
     } 
    } 
    #endregion 
} 

他のすべては、私はそれを考えていない正常に動作しますので、すべてのモデルを含める必要があります。

答えて

2

最初に、 'async void'をこれまで使用しないでください。これは、イベントハンドラでは適切な場合もありますが、ここではできません。 'async Task'を使用し、GetFacebookメソッド(または他の非同期メソッドの1つ)が実際に終了した後、ContinueWith構造を使用してOnPropertyChangedを呼び出すことができるようになります。

Secondイベントが初期化されていないため、例外がスローされています。

private ObservableCollection<FB> _events = new ObservableCollection<FB>(); 

また、GetFacebookDataを再度呼び出す場合は、このリストをクリアすることを忘れないでください。

+0

ありがとうございます、初期設定が完了しました。他のすべてのObservableObjectsが満たされる前にinitilizeを取得する必要がないように思われたので、私はそれについて考えませんでした...また、私は非同期タスクを開始しましたが、ループで発生する必要があるためトラブルに陥りました。私は仕事でもう一度やり直します。ありがとうございます –

+0

私のリストボックスが空のままになっている理由を知っていますか?プロパティのカウントは61ですか? –

+0

どのプロパティですか?イベント? – VitaliyK

関連する問題