【发布时间】:2017-01-15 06:38:27
【问题描述】:
在我的 .Net Mvvm/MVC 学习过程中,我偶然发现了另一个问题。
我正在尝试填充 ObservableObject 属性,以便将其绑定到我的窗口或用户控件。该属性应填充到执行 GET 请求的 private async void 中。
由于您不能在属性中使用await 方法/函数,因此我尝试在方法中填充属性。它总是给NullReferenceException。
在设置换行符并按 F11(跳过)很多次后,我发现除了所需的属性 Events 之外,所有内容都已正确填充。
流程是这样的:
- 您选择一个国家 -> selectedItem 绑定到 SelectedCountry
- 选择一个“省” -> selectedItem 绑定到 SelectedProvince
- 选择一个城市 -> selectedItem 绑定到 SelectedCity
上述每个属性都会触发一个与我的 API 通信的方法,该 API 用于从我的数据库中获取数据并显示/返回它。 ObservableObject 属性“国家、省、市”在这些与 API 通信的方法中设置。此时一切仍然正常。
当设置City 属性时,它调用方法GetOrgsByCity() 填充另一个ObservableObject 属性Orgs。在Orgs 的setter 中,调用了GetFacebookData(FB_IDS)。此方法需要一个List<string> 类型的参数,并且是一个返回LINQ 过滤列表的属性。一切仍然正常。
问题来了:
在GetFacebookData(FB_IDS) 方法中,我试图填充一个名为Events 的ObservableObject 属性,该方法向Facebook 执行GET 请求。 IsSuccessStatusCode 等于 true 并且除了 ObservableObject 属性 Events 之外的所有内容都被正确填充。
我正在“转换”结果列表 (List<FB> data) 与 foreach 以填充 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
}
由于其他一切正常,我认为没有必要包含所有模型。
【问题讨论】: