API的响应Json没有绑定到我的模型



我试图从我的Country模型显示CountryText。它似乎拿起数组,并在listview中显示空白文本块,但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>

ViewModel

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; }
}

数组显示在左侧ListView

Json输出是这样的

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

有几个问题需要解决。

首先,仅仅实现INotifyPropertyChanged接口是不足以实现数据绑定的。每次更新属性时都需要调用OnPropertyChanged(propertyName)。这通常在getter/setter中完成。(另外,如果正在进行数据绑定,则不应该使用auto属性)。另外,你的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));
}
}

您的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
}

最新更新