英文:
Why is my ListView not populating with data? No errors and I can see the data in the console in VS, .NET Maui application using JSON from API
问题
以下是您的Model类 - Models文件夹中的Posts.cs部分:
using Newtonsoft.Json;
using System.Text.Json.Serialization;
namespace App.Models
{
public class CommunityBannerImage
{
[JsonPropertyName("mimetype")] public string Mimetype { get; set; }
[JsonPropertyName("width")] public int Width { get; set; }
[JsonPropertyName("height")] public int Height { get; set; }
[JsonPropertyName("size")] public int Size { get; set; }
[JsonPropertyName("averageColor")] public string AverageColor { get; set; }
[JsonPropertyName("url")] public string Url { get; set; }
[JsonPropertyName("copies")] public List<Copy> Copies { get; set; }
}
public class CommunityProPic
{
[JsonPropertyName("mimetype")] public string Mimetype { get; set; }
[JsonPropertyName("width")] public int Width { get; set; }
[JsonPropertyName("height")] public int Height { get; set; }
[JsonPropertyName("size")] public int Size { get; set; }
[JsonPropertyName("averageColor")] public string AverageColor { get; set; }
[JsonPropertyName("url")] public string Url { get; set; }
[JsonPropertyName("copies")] public List<Copy> Copies { get; set; }
}
public class Copy
{
[JsonPropertyName("copyId")] public string CopyId { get; set; }
[JsonPropertyName("width")] public int Width { get; set; }
[JsonPropertyName("height")] public int Height { get; set; }
[JsonPropertyName("size")] public int Size { get; set; }
[JsonPropertyName("url")] public string Url { get; set; }
[JsonPropertyName("objectFit")] public string ObjectFit { get; set; }
}
public class Image
{
[JsonPropertyName("mimetype")] public string Mimetype { get; set; }
[JsonPropertyName("width")] public int Width { get; set; }
[JsonPropertyName("height")] public int Height { get; set; }
[JsonPropertyName("size")] public int Size { get; set; }
[JsonPropertyName("averageColor")] public string AverageColor { get; set; }
[JsonPropertyName("url")] public string Url { get; set; }
[JsonPropertyName("copies")] public List<Copy> Copies { get; set; }
}
public class Link
{
[JsonPropertyName("url")] public string Url { get; set; }
[JsonPropertyName("hostname")] public string Hostname { get; set; }
[JsonPropertyName("image")] public Image Image { get; set; }
}
public class Post
{
[JsonPropertyName("id")] public string Id { get; set; }
[JsonPropertyName("type")] public string Type { get; set; }
[JsonPropertyName("publicId")] public string PublicId { get; set; }
[JsonPropertyName("userId")] public string UserId { get; set; }
[JsonPropertyName("username")] public string Username { get; set; }
[JsonPropertyName("userGroup")] public string UserGroup { get; set; }
[JsonPropertyName("userDeleted")] public bool UserDeleted { get; set; }
[JsonPropertyName("isPinned")] public bool IsPinned { get; set; }
[JsonPropertyName("communityId")] public string CommunityId { get; set; }
[JsonPropertyName("communityName")] public string CommunityName { get; set; }
[JsonPropertyName("communityProPic")] public CommunityProPic CommunityProPic { get; set; }
[JsonPropertyName("communityBannerImage")] public CommunityBannerImage CommunityBannerImage { get; set; }
[JsonPropertyName("title")] public string Title { get; set; }
[JsonPropertyName("body")] public object Body { get; set; }
[JsonPropertyName("link")] public Link Link { get; set; }
[JsonPropertyName("locked")] public bool Locked { get; set; }
[JsonPropertyName("lockedBy")] public object LockedBy { get; set; }
[JsonPropertyName("lockedAt")] public object LockedAt { get; set; }
[JsonPropertyName("upvotes")] public int Upvotes { get; set; }
[JsonPropertyName("downvotes")] public int Downvotes { get; set; }
[JsonPropertyName("hotness")] public object Hotness { get; set; }
[JsonPropertyName("createdAt")] public DateTime CreatedAt { get; set; }
[JsonPropertyName("editedAt")] public object EditedAt { get; set; }
[JsonPropertyName("lastActivityAt")] public DateTime LastActivityAt { get; set; }
[JsonPropertyName("deleted")] public bool Deleted { get; set; }
[JsonPropertyName("deletedAt")] public object DeletedAt { get; set; }
[JsonPropertyName("deletedContent")] public bool DeletedContent { get; set; }
[JsonPropertyName("noComments")] public int NoComments { get; set; }
[JsonPropertyName("comments")] public object Comments { get; set; }
[JsonPropertyName("commentsNext")] public object CommentsNext { get; set; }
[JsonPropertyName("userVoted")] public bool UserVoted { get; set; }
[JsonPropertyName("userVotedUp")] public bool? UserVotedUp { get; set; }
}
[JsonObject]
public class Root
{
[JsonPropertyName("posts")] public List<Post> Posts { get; set; }
[JsonPropertyName("next")] public string Next { get; set; }
}
}
这是您的ViewModel类 - ViewModels文件夹中的PostsViewModel.cs部分:
using App.Models;
using System.Text.Json;
using System.Windows.Input;
namespace App.ViewModels
{
public class PostsViewModel : BaseViewModel
{
private string _type;
public string Type { get => _type; set { _type = value; OnPropertyChanged(nameof(Type)); } }
private string _username;
public string Username { get => _username; set { _username = value; OnPropertyChanged(nameof(Username)); } }
private string _communityName;
public string CommunityName { get => _communityName; set { _communityName = value; OnPropertyChanged(nameof(CommunityName)); } }
private string _title;
public string Title { get => _title; set { _title = value; OnPropertyChanged(nameof(Title)); } }
private string _body;
public string Body { get => _body; set { _body = value; OnPropertyChanged(nameof(Body)); } }
public ICommand LoadPostsCommand { get; set; }
public PostsViewModel()
{
LoadPostsCommand = new Command(async () => await LoadPosts());
}
private async Task LoadPosts()
{
var url = "https://discuit.net/api/posts";
var client = new HttpClient();
var response = await client.GetAsync(url);
var successCode = await client.GetAsync(url);
// validate connection
if (successCode.IsSuccessStatusCode)
{
Console.WriteLine("-----------------------------------
<details>
<summary>英文:</summary>
Here is my Model class - Posts.cs in Models folder:
using Newtonsoft.Json;
using System.Text.Json.Serialization;
namespace App.Models
{
// Root myDeserializedClass = JsonConvert.DeserializeObject<Root>(myJsonResponse);
public class CommunityBannerImage
{
[JsonPropertyName("mimetype")] public string Mimetype { get; set; }
[JsonPropertyName("width")] public int Width { get; set; }
[JsonPropertyName("height")] public int Height { get; set; }
[JsonPropertyName("size")] public int Size { get; set; }
[JsonPropertyName("averageColor")] public string AverageColor { get; set; }
[JsonPropertyName("url")] public string Url { get; set; }
[JsonPropertyName("copies")] public List<Copy> Copies { get; set; }
}
public class CommunityProPic
{
[JsonPropertyName("mimetype")] public string Mimetype { get; set; }
[JsonPropertyName("width")] public int Width { get; set; }
[JsonPropertyName("height")] public int Height { get; set; }
[JsonPropertyName("size")] public int Size { get; set; }
[JsonPropertyName("averageColor")] public string AverageColor { get; set; }
[JsonPropertyName("averageColor")] public string Url { get; set; }
[JsonPropertyName("copies")] public List<Copy> Copies { get; set; }
}
public class Copy
{
[JsonPropertyName("copyId")] public string CopyId { get; set; }
[JsonPropertyName("width")] public int Width { get; set; }
[JsonPropertyName("height")] public int Height { get; set; }
[JsonPropertyName("size")] public int Size { get; set; }
[JsonPropertyName("url")] public string Url { get; set; }
[JsonPropertyName("objectFit")] public string ObjectFit { get; set; }
}
public class Image
{
[JsonPropertyName("mimetype")] public string Mimetype { get; set; }
[JsonPropertyName("width")] public int Width { get; set; }
[JsonPropertyName("height")] public int Height { get; set; }
[JsonPropertyName("size")] public int Size { get; set; }
[JsonPropertyName("averageColor")] public string AverageColor { get; set; }
[JsonPropertyName("url")] public string Url { get; set; }
[JsonPropertyName("copies")] public List<Copy> Copies { get; set; }
}
public class Link
{
[JsonPropertyName("url")] public string Url { get; set; }
[JsonPropertyName("hostname")] public string Hostname { get; set; }
[JsonPropertyName("image")] public Image Image { get; set; }
}
public class Post
{
[JsonPropertyName("id")] public string Id { get; set; }
[JsonPropertyName("type")] public string Type { get; set; }
[JsonPropertyName("publicId")] public string PublicId { get; set; }
[JsonPropertyName("userId")] public string UserId { get; set; }
[JsonPropertyName("username")] public string Username { get; set; }
[JsonPropertyName("userGroup")] public string UserGroup { get; set; }
[JsonPropertyName("userDeleted")] public bool UserDeleted { get; set; }
[JsonPropertyName("isPinned")] public bool IsPinned { get; set; }
[JsonPropertyName("communityId")] public string CommunityId { get; set; }
[JsonPropertyName("communityName")] public string CommunityName { get; set; }
[JsonPropertyName("communityProPic")] public CommunityProPic CommunityProPic { get; set; }
[JsonPropertyName("communityBannerImage")] public CommunityBannerImage CommunityBannerImage { get; set; }
[JsonPropertyName("title")] public string Title { get; set; }
[JsonPropertyName("body")] public object Body { get; set; }
[JsonPropertyName("link")] public Link Link { get; set; }
[JsonPropertyName("locked")] public bool Locked { get; set; }
[JsonPropertyName("lockedBy")] public object LockedBy { get; set; }
[JsonPropertyName("lockedAt")] public object LockedAt { get; set; }
[JsonPropertyName("upvotes")] public int Upvotes { get; set; }
[JsonPropertyName("downvotes")] public int Downvotes { get; set; }
[JsonPropertyName("hotness")] public object Hotness { get; set; }
[JsonPropertyName("createdAt")] public DateTime CreatedAt { get; set; }
[JsonPropertyName("editedAt")] public object EditedAt { get; set; }
[JsonPropertyName("lastActivityAt")] public DateTime LastActivityAt { get; set; }
[JsonPropertyName("deleted")] public bool Deleted { get; set; }
[JsonPropertyName("deletedAt")] public object DeletedAt { get; set; }
[JsonPropertyName("deletedContent")] public bool DeletedContent { get; set; }
[JsonPropertyName("noComments")] public int NoComments { get; set; }
[JsonPropertyName("comments")] public object Comments { get; set; }
[JsonPropertyName("commentsNext")] public object CommentsNext { get; set; }
[JsonPropertyName("userVoted")] public bool UserVoted { get; set; }
[JsonPropertyName("userVotedUp")] public bool? UserVotedUp { get; set; }
}
[JsonObject]
public class Root
{
[JsonPropertyName("posts")] public List<Post> Posts { get; set; }
[JsonPropertyName("next")] public string Next { get; set; }
}
}
Here is my ViewModel - PostsViewModel.cs in ViewModels folder:
using App.Models;
using System.Text.Json;
using System.Windows.Input;
namespace App.ViewModels;
public class PostsViewModel : BaseViewModel
{
private string _type;
public string Type { get => _type; set { _type = value; OnPropertyChanged(nameof(Type)); } }
private string _username;
public string Username { get => _username; set { _username = value; OnPropertyChanged(nameof(Username)); } }
private string _communityName;
public string CommunityName { get => _communityName; set { _communityName = value; OnPropertyChanged(nameof(CommunityName)); } }
private string _title;
public string Title { get => _title; set { _title = value; OnPropertyChanged(nameof(Title)); } }
private string _body;
public string Body { get => _body; set { _body = value; OnPropertyChanged(nameof(Body)); } }
public ICommand LoadPostsCommand { get; set; }
public PostsViewModel()
{
LoadPostsCommand = new Command(async () => await LoadPosts());
}
private async Task LoadPosts()
{
var url = $"https://discuit.net/api/posts";
var client = new HttpClient();
var response = await client.GetAsync(url);
var successCode = await client.GetAsync(url);
// validate connection
if (successCode.IsSuccessStatusCode)
{
Console.WriteLine("-----------------------------------");
Console.WriteLine("Code 200 - Successful Connection to REST API");
Console.WriteLine("-----------------------------------");
var data = await response.Content.ReadAsStringAsync();
var options = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true,
};
var posts = JsonSerializer.Deserialize<Posts>(data, options);
Console.WriteLine("-----------------------------------");
Console.WriteLine("Data: " + data);
Console.WriteLine("Posts: " + posts);
Console.WriteLine("-----------------------------------");
var Type = posts.Type;
var Username = posts.Username;
var CommunityName = posts.CommunityName;
var Title = posts.Title;
var Body = posts.Body;
}
else
{
Console.WriteLine("Error connecting to API");
}
}
}
Here is my Content Page code behind - HomePage.xaml.cs in Views folder:
using App.ViewModels;
namespace App.Views;
public partial class HomePage : ContentPage
{
public HomePage()
{
InitializeComponent();
BindingContext = new PostsViewModel();
}
}
Here is my Content Page - HomePage.xaml in Views folder
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="App.Views.HomePage" Title="Posts"
xmlns:local="clr-namespace:App"
xmlns:vm="clr-namespace:App.ViewModels"
x:DataType="vm:PostsViewModel"
>
<ListView ItemsSource="{Binding LoadPostsCommand}">
<ListView.Header>
<VerticalStackLayout
Spacing="25"
Padding="30,0"
VerticalOptions="Center">
<Button
x:Name="UpdateBtn"
Text="Load Posts"
Command="{Binding LoadPostsCommand}"
Margin="10"
/>
</VerticalStackLayout>
</ListView.Header>
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="{Binding Title}" Detail="{Binding Body}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage>
and here is the BaseViewModel.cs page that HomePage inherits:
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace Disc.ViewModels;
public abstract class BaseViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
protected bool SetProperty<TValue>(ref TValue backingField, TValue value, [CallerMemberName] string propertyName = "")
{
if (Comparer<TValue>.Default.Compare(backingField, value) == 0)
{
return false;
}
backingField = value;
OnPropertyChanged(propertyName);
return true;
}
}
and finally, here is my debug output:
[DOTNET] -----------------------------------
[DOTNET] Code 200 - Successful Connection to REST API
[DOTNET] -----------------------------------
[monodroid-assembly] open_from_bundles: failed to load assembly Newtonsoft.Json.dll
Loaded assembly: /data/data/com.companyname.app/files/.override/Newtonsoft.Json.dll [External]
[DOTNET] -----------------------------------
[DOTNET] Data: {"posts":[{"id":"1775d55eb7515d9d1e2d7481","type":"text","publicId":"pTJMsSk9","userId":"176caa4ff743f7b0a2fa3ec2","username":"pH_low","userGroup":"mods","userDeleted":false,"isPinned":false,"communityId":"1770a5ebb222dcb14b21f6cd","communityName":"DiscoApp","communityProPic":null,"communityBannerImage":null,"title":"Update - July 17th","body":"Hello everyone!
[DOTNET] Posts: App.Models.Posts
[DOTNET] -----------------------------------
Thanks so much for taking a look!!
[1]: https://stackoverflow.com/questions/76683374/how-to-get-json-response-into-a-listview-in-net-maui
</details>
# 答案1
**得分**: 1
创建一个类型为`Root`的属性在你的`VM`中。
```csharp
[ObservableProperty]
Root 数据 { get; set; }
将你的数据反序列化到该属性中。
Data = JsonSerializer.Deserialize<Root>(data, options);
然后将Data.Posts
用作你的ItemsSource
。
<ListView ItemsSource="{Binding Data.Posts}">
英文:
create a property in your VM
of type Root
[ObservableProperty]
Root data { get; set; }
deserialize your data into that property
Data = JsonSerializer.Deserialize<Root>(data, options);
then use Data.Posts
as your ItemsSource
<ListView ItemsSource="{Binding Data.Posts}">
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论