如何解决Xamarin分组的ListView:如何将JSON转换为为分组的ListView创建的模型
我正在将来自ASP.NET Core后端的类别作为数组加载到Xamarin应用程序中,以用于具有列表项(如此处https://docs.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/listview/customizing-list-appearance#grouping)的ListView。
09-06 23:25:36.679 W/SSLCertificateSocketFactory(29717): Bypassing SSL security checks at caller's request
[0:] Newtonsoft.Json.JsonSerializationException: Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'BoerPlaza.Models.Products.Category' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.
To fix this error either change the JSON to a JSON array (e.g. [1,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer,not a collection type like an array or List<T>) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.
Path '[0].id',line 1,position 7.
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject (Newtonsoft.Json.JsonReader reader,System.Type objectType,Newtonsoft.Json.Serialization.JsonContract contract,Newtonsoft.Json.Serialization.JsonProperty member,Newtonsoft.Json.Serialization.JsonContainerContract containerContract,Newtonsoft.Json.Serialization.JsonProperty containerMember,System.Object existingValue) [0x003a0] in <2073514815234917a5e8f91b0b239405>:0
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal (Newtonsoft.Json.JsonReader reader,System.Object existingValue) [0x0006d] in <2073514815234917a5e8f91b0b239405>:0
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateList (System.Collections.IList list,Newtonsoft.Json.JsonReader reader,Newtonsoft.Json.Serialization.JsonArrayContract contract,Newtonsoft.Json.Serialization.JsonProperty containerProperty,System.String id) [0x00173] in <2073514815234917a5e8f91b0b239405>:0
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateList (Newtonsoft.Json.JsonReader reader,System.Object existingValue,System.String id) [0x000dc] in <2073514815234917a5e8f91b0b239405>:0
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal (Newtonsoft.Json.JsonReader reader,System.Object existingValue) [0x0007f] in <2073514815234917a5e8f91b0b239405>:0
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize (Newtonsoft.Json.JsonReader reader,System.Boolean checkAdditionalContent) [0x000db] in <2073514815234917a5e8f91b0b239405>:0
at Newtonsoft.Json.JsonSerializer.DeserializeInternal (Newtonsoft.Json.JsonReader reader,System.Type objectType) [0x00054] in <2073514815234917a5e8f91b0b239405>:0
at Newtonsoft.Json.JsonSerializer.Deserialize (Newtonsoft.Json.JsonReader reader,System.Type objectType) [0x00000] in <2073514815234917a5e8f91b0b239405>:0
at Newtonsoft.Json.JsonConvert.DeserializeObject (System.String value,System.Type type,Newtonsoft.Json.JsonSerializerSettings settings) [0x0002d] in <2073514815234917a5e8f91b0b239405>:0
at Newtonsoft.Json.JsonConvert.DeserializeObject[T] (System.String value,Newtonsoft.Json.JsonSerializerSettings settings) [0x00000] in <2073514815234917a5e8f91b0b239405>:0
at Newtonsoft.Json.JsonConvert.DeserializeObject[T] (System.String value) [0x00000] in <2073514815234917a5e8f91b0b239405>:0
at BoerPlaza.Services.CategoryDataStore.GetCategoriesParentAsync () [0x0013b] in C:\Users\QuanDar\source\repos\BoerPlaza\Frontend\BoerPlaza\BoerPlaza\Services\CategoryDataStore.cs:47
at BoerPlaza.ViewModels.BrowseCategoryViewModel.ExecuteLoadCategoriesCommand () [0x00068] in C:\Users\QuanDar\source\repos\BoerPlaza\Frontend\BoerPlaza\BoerPlaza\ViewModels\BrowseCategoryViewModel.cs:49
该模型的问题是必须从ObservableCollection继承。所有其他模型都运行良好,这只是由于继承而无法进行的工作。当我删除继承项时,一切工作都很好,但是那时我无法在ListView中对项目进行分组。
尝试列表,而不是ObservableCollection。没关系。 Xamarin模型:(不包括EF Core模型,但JSON应该显示可用的东西)
public class Category : ObservableCollection<Category>
{
public int Id { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public Category Parent { get; set; }
public Image Image { get; set; }
public ObservableCollection<Category> Children => this;
public Category(string title)
{
this.Title = title;
}
public Category()
{
}
}
后端的JSON:
[
{
"id": 1,"title": "Vlees","description": null,"parent": null,"image": {
"alt": "Bedrijven WordPress themes","pathThumbnail": "Templates/constructie.jpg"
},"children": [
{
"id": 5,"title": " Kip","image": {
"alt": "Bedrijven WordPress themes","pathThumbnail": "Templates/constructie.jpg"
},"children": []
},{
"id": 6,"title": "Koe","pathThumbnail": "Templates/constructie.jpg"
},"children": []
}
]
},{
"id": 2,"title": "Groente","image": {
"alt": "Bedrijven WordPress themes","pathThumbnail": "Templates/constructie.jpg"
},"children": [
{
"id": 9,"title": "Boemkool","children": []
}
]
},{
"id": 3,"title": "Fruit","image": {
"alt": "Bedrijven WordPress themes","children": [
{
"id": 10,"title": "Appel","children": []
},{
"id": 11,"title": "Peer",{
"id": 4,"title": "Kruiden","children": [
{
"id": 12,"title": "Knoflook",{
"id": 13,"title": "Peterselie","children": []
}
]
}
]
HTTP服务
public async Task<IEnumerable<Category>> GetCategoriesParentAsync()
{
if (IsConnected)
{
var json = await client.GetStringAsync($"api/products/categories/parent");
return await Task.Run(() => JsonConvert.DeserializeObject<IEnumerable<Category>>(json));
}
return this.categories;
}
ViewModel: 当我自己设置数组时,一切正常。
public ObservableCollection<Category> Categories { get; set; }
...
public async Task ExecuteLoadCategoriesCommand()
{
IsBusy = true;
this.PreviousCategoryHolder.Add(this.Categories);
try
{
Categories.Clear();
// This does not work and throws the error
//var categories = await CategoryStore.GetCategoriesParentAsync();
//foreach (var category in categories)
//{
// Categories.Add(category);
//}
// when I do it like this,it works and displays the items.
this.Categories = new ObservableCollection<Category>
{
new Category("Vlees")
{
new Category("kip"),new Category("kip file")
},new Category("Groente")
{
new Category("Appel"),new Category("Banaan")
}
};
}
catch (Exception ex)
{
Debug.WriteLine(ex);
}
finally
{
IsBusy = false;
}
}
xaml:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="BoerPlaza.Views.BrowsePage">
<!-- binding context is in code behind -->
<ContentPage.Content>
<ListView x:Name ="categoriesListView"
IsGroupingEnabled="true"
ItemTapped="Handle_ItemTapped"
CachingStrategy="RecycleElement"
>
<ListView.GroupHeaderTemplate>
<DataTemplate>
<TextCell Text="{Binding Title}"/>
</DataTemplate>
</ListView.GroupHeaderTemplate>
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="{Binding Title}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage.Content>
</ContentPage>
谢谢!
解决方法
您可以创建一个新的视图模型,然后将解析的数据设置为该视图模型。
例如:
类 GroupViewModel :
public class GroupViewModel:ObservableCollection<Category>
{
public int Id { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public Category Parent { get; set; }
//public Image Image { get; set; }
public ObservableCollection<Category> Children => this;
public GroupViewModel(string title)
{
this.Title = title;
}
}
课程类别:
public class Category
{
public int Id { get; set; }
public string Title { get; set; }
public string Description { get; set; }
//public Category parent { get; set; }
public List<Category> Children;
}
设置 ItemSource :
var data = JsonConvert.DeserializeObject<List<Category>>(json);// the json you request from service
ObservableCollection<GroupViewModel> groupList = new ObservableCollection<GroupViewModel>();
foreach (var item in data)
{
GroupViewModel children = new GroupViewModel(item.Title);
foreach (var i in item.Children)
{
children.Add(i);
}
groupList.Add(children);
}
categoriesListView.ItemsSource = groupList;
,
通过使用NewtonSoft nuget(https://www.nuget.org/packages/Newtonsoft.Json/),您可以在json属性和模型属性之间定义双射。就是这样:
public class Product
{
[JsonProperty("id")]
public int Id { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("price")]
public decimal Price { get; set; }
[JsonProperty("imageUrl")]
public string ImageUrl { get; set; }
}
然后您的HTTP服务必须如下所示:
var response = await client.GetAsync(your_url);
var result = await response.Content.ReadAsStringAsync();
var list = JsonConvert.DeserializeObject<List<Product>>(result);
您的后端端点应如下所示:
public async Task<IActionResult> GetProductsAsync()
{
var dataContext = productRepository.GetAll();
return Ok(await dataContext.ToListAsync());
}
我正在使用存储库模式设计,您可以直接处理DataContext DB
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。