【问题标题】:Response Json from API is not binding to my Model来自 API 的响应 Json 未绑定到我的模型
【发布时间】:2021-10-17 16:52:17
【问题描述】:

我试图从我的Country 模型中显示CountryText。它似乎拿起了数组并在列表视图中显示了空白文本块,但 CountryText 没有显示。

我刚开始学习数据绑定,所以我不确定我是否遗漏了什么

XML

<Window x:Class="CovidApi.View.CasesWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:vm="clr-namespace:CovidApi.ViewModel"
        xmlns:local="clr-namespace:CovidApi.View"
        mc:Ignorable="d"
        Title="CasesWindow"
        Height="450"
        Width="800">

    <Window.Resources>
        <vm:CasesVM x:Key="vm"/>
    </Window.Resources>
    
    <DockPanel DataContext="{StaticResource vm}">
        <Grid>
            <ListView Width="160"
                      ItemsSource="{Binding Countries}">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding CountryText}"/>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
        </Grid>

        <Grid>
            <ListView Width="160">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <TextBlock/>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
        </Grid>

        <Grid>
            
        </Grid>
    </DockPanel>
</Window>

视图模型

namespace CovidApi.ViewModel
{
    public class CasesVM : INotifyPropertyChanged
    {
        public ObservableCollection<Country> Countries { get; set; }

        public CasesVM()
        {
            Countries = new ObservableCollection<Country>();
        }

        public async void MakeQuery()
{
            var countries = await Covid19Helper.GetLatestAllCountries();

            Countries.Clear();
            foreach (var country in countries)
            {
                Countries.Add(country);
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

API 助手

namespace CovidApi.ViewModel.Helpers
{
    public class Covid19Helper
    {
        public static async Task<List<Country>> GetLatestAllCountries()
        {
            List<Country> countries = new();

            string url = "https://covid-19-tracking.p.rapidapi.com/v1";

            using (HttpClient client = new())
            {
                client.DefaultRequestHeaders.Add("x-rapidapi-key", "**apiKey**");
                client.DefaultRequestHeaders.Add("x-rapidapi-host", "covid-19-tracking.p.rapidapi.com");
                var response = await client.GetAsync(url);
                string json = await response.Content.ReadAsStringAsync();
                countries = JsonConvert.DeserializeObject<List<Country>>(json);
            }

            return countries;
        }
    }
}

型号

public class Country
    {
        public string ActiveCasesText { get; set; }
        public string CountryText { get; set; }
        public string LastUpdate { get; set; }
        public string NewCasesText { get; set; }
        public string NewDeathsText { get; set; }
        public string TotalCasesText { get; set; }
        public string TotalDeathsText { get; set; }
        public string TotalRecoveredText { get; set; }
    }

Array showing in left ListView

Json comes out like this

但是被反序列化的变量 - countries = JsonConvert.DeserializeObject&lt;List&lt;Country&gt;&gt;(json); 将 Country 模型的所有属性显示为 null

【问题讨论】:

  • 您的示例代码中似乎包含了您的 API 密钥。我建议删除它,特别是因为您已经提供了一个示例 API 响应。
  • 我已经删除了它,但这并不是什么大不了的事。它只是一个学习工具

标签: c# wpf data-binding api-design


【解决方案1】:

有几个问题需要解决。

首先,仅仅实现INotifyPropertyChanged 接口不足以进行数据绑定。每次更新属性时,您都需要致电OnPropertyChanged(propertyName)。这通常在 getter/setter 中完成。 (此外,如果您正在执行数据绑定,则不应使用自动属性)。此外,您的Country 类也需要实现INotifyPropertyChanged。

我还建议在您的OnPropertyChanged 方法中使用CallerMemberName。这样您就不必在调用 OnPropertyChanged 时包含属性名称 - 而是在运行时为您处理。

其次,由于名称不匹配,JSON 反序列化器不知道如何填充您的 Country 模型。例如,在您的模型中,您有 CountryText,我假设它应该由 API 中的 Country_text 填充。您应该将模型中的属性与相应的 JSON 名称相匹配,如下例所示。

因此,在您的示例中,您的国家/地区模型的属性设置如下:

class YourModel : INotifyPropertyChanged
{
    private string someProperty;
    [JsonProperty(“<name of this property in your JSON response>”)]
    public string SomeProperty
    {
        get => someProperty;
        set { someProperty = value; OnPropertyChanged(); }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    public void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

您的 ViewModel 将如下所示:

class YourViewModel : INotifyPropertyChanged
{
    private ObservableCollection<YourModel> models;
    public ObservableCollection<YourModel> Models
    {
        get => models;
        set { models = value; OnPropertyChanged(); }
    }

    // don’t forget to insert your constructor, other properties, 
    // other methods etc somewhere in this class too

    public event PropertyChangedEventHandler PropertyChanged;
    public void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

【讨论】:

    【解决方案2】:

    您的 json 属性名称与 c# 名称不同,请尝试映射

    
    public class Country
    {
           [JsonProperty("Active Cases_text ")] 
            public string ActiveCasesText { get; set; }
            [JsonProperty("Country_text ")] 
            public string CountryText { get; set; }
          .... and so on
    }
    

    【讨论】:

    • 这是一个问题,但不足以修复数据绑定,因为 OP 没有在 Country 中实现 INotifyPropertyChanged,也没有在任何地方调用 OnPropertyChanged()
    猜你喜欢
    • 2013-04-28
    • 2017-03-06
    • 2012-11-06
    • 1970-01-01
    • 2016-08-06
    • 2014-09-10
    • 2021-07-21
    • 2019-12-07
    • 2019-02-09
    相关资源
    最近更新 更多