gpt4 book ai didi

c# Mvvm 用来自 GET 请求的数据填充 ObservableObject 属性

转载 作者:行者123 更新时间:2023-12-03 11:03:33 25 4
gpt4 key购买 nike

在我的 .Net Mvvm/MVC 学习过程中,我偶然发现了另一个问题。

我正在尝试填充 ObservableObject 属性,以便可以将其绑定(bind)到我的窗口或用户控件。该属性应填写在 private async void 中执行 GET 请求。

因为你不能await属性内的方法/函数,我试图填充方法内的属性。它总是给出 NullReferenceException .
在设置换行符并按 F11(跳过)很多次后,我发现除了所需的属性 Events 之外,所有内容都已正确填充。 .

流程是这样的:

  • 您选择一个国家 -> selectedItem 绑定(bind)到 SelectedCountry
  • 选择一个“省”-> selectedItem 绑定(bind)到 SelectedProvince
  • 选择一个城市 -> selectedItem 绑定(bind)到 SelectedCity

  • 以上每个属性都会触发一个与我的 API 通信的方法,该 API 用于从我的数据库中获取数据并显示/返回它。 ObservableObject在这些与 API 通信的方法中设置属性“国家、省、市”。此时一切仍然正常。

    City属性被设置,它调用一个方法 GetOrgsByCity()填充另一个 ObservableObject 属性 Orgs .在 Orgs 的 setter 中, GetFacebookData(FB_IDS)叫做。此方法需要一个类型为 List<string> 的参数并且是一个由 LINQ 返回过滤列表的属性。一切仍然正常。

    问题来了:

    GetFacebookData(FB_IDS)方法我正在尝试填写 ObservableObject名为 Events 的属性,该方法向 Facebook 执行 GET 请求。 IsSuccessStatusCode等于 true除了 ObservableObject 之外,所有内容都已正确填写房产 Events .

    我正在将结果列表( List<FB> data )“转换”为 foreach获取 Events填充。当我运行它时,它会中断并抛出 NullReferenceException .
    据说 Events为 null 或其他东西,因为其他变量已正确填充。

    有谁知道为什么 Events属性(property)拍个NullReferenceException当试图填补它?

    xaml(绑定(bind)的地方):
        <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
    }

    由于其他一切都很好,我认为没有必要包括所有模型。

    最佳答案

    首先-永远不要使用'async void'-这有时可能只适用于事件处理程序,但在这里不适用。使用“异步任务”,然后您将能够在 GetFacebook 方法(或其他异步方法之一)真正完成后使用 ContinueWith 构造调用 OnPropertyChanged。

    第二 - 事件抛出异常,因为它没有被初始化。你应该改变:

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

    如果您将再次调用 GetFacebookData,也不要忘记清除此列表。

    关于c# Mvvm 用来自 GET 请求的数据填充 ObservableObject 属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41655596/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com