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

huangapple go评论97阅读模式
英文:

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(&quot;mimetype&quot;)] public string Mimetype { get; set; }
[JsonPropertyName(&quot;width&quot;)] public int Width { get; set; }
[JsonPropertyName(&quot;height&quot;)] public int Height { get; set; }
[JsonPropertyName(&quot;size&quot;)] public int Size { get; set; }
[JsonPropertyName(&quot;averageColor&quot;)] public string AverageColor { get; set; }
[JsonPropertyName(&quot;averageColor&quot;)] public string Url { get; set; }
[JsonPropertyName(&quot;copies&quot;)] public List&lt;Copy&gt; Copies { get; set; }
}
public class Copy
{
[JsonPropertyName(&quot;copyId&quot;)] public string CopyId { get; set; }
[JsonPropertyName(&quot;width&quot;)] public int Width { get; set; }
[JsonPropertyName(&quot;height&quot;)] public int Height { get; set; }
[JsonPropertyName(&quot;size&quot;)] public int Size { get; set; }
[JsonPropertyName(&quot;url&quot;)] public string Url { get; set; }
[JsonPropertyName(&quot;objectFit&quot;)] public string ObjectFit { get; set; }
}
public class Image
{
[JsonPropertyName(&quot;mimetype&quot;)] public string Mimetype { get; set; }
[JsonPropertyName(&quot;width&quot;)] public int Width { get; set; }
[JsonPropertyName(&quot;height&quot;)] public int Height { get; set; }
[JsonPropertyName(&quot;size&quot;)] public int Size { get; set; }
[JsonPropertyName(&quot;averageColor&quot;)] public string AverageColor { get; set; }
[JsonPropertyName(&quot;url&quot;)] public string Url { get; set; }
[JsonPropertyName(&quot;copies&quot;)] public List&lt;Copy&gt; Copies { get; set; }
}
public class Link
{
[JsonPropertyName(&quot;url&quot;)] public string Url { get; set; }
[JsonPropertyName(&quot;hostname&quot;)] public string Hostname { get; set; }
[JsonPropertyName(&quot;image&quot;)] public Image Image { get; set; }
}
public class Post
{
[JsonPropertyName(&quot;id&quot;)] public string Id { get; set; }
[JsonPropertyName(&quot;type&quot;)] public string Type { get; set; }
[JsonPropertyName(&quot;publicId&quot;)] public string PublicId { get; set; }
[JsonPropertyName(&quot;userId&quot;)] public string UserId { get; set; }
[JsonPropertyName(&quot;username&quot;)] public string Username { get; set; }
[JsonPropertyName(&quot;userGroup&quot;)] public string UserGroup { get; set; }
[JsonPropertyName(&quot;userDeleted&quot;)] public bool UserDeleted { get; set; }
[JsonPropertyName(&quot;isPinned&quot;)] public bool IsPinned { get; set; }
[JsonPropertyName(&quot;communityId&quot;)] public string CommunityId { get; set; }
[JsonPropertyName(&quot;communityName&quot;)] public string CommunityName { get; set; }
[JsonPropertyName(&quot;communityProPic&quot;)] public CommunityProPic CommunityProPic { get; set; }
[JsonPropertyName(&quot;communityBannerImage&quot;)] public CommunityBannerImage CommunityBannerImage { get; set; }
[JsonPropertyName(&quot;title&quot;)] public string Title { get; set; }
[JsonPropertyName(&quot;body&quot;)] public object Body { get; set; }
[JsonPropertyName(&quot;link&quot;)] public Link Link { get; set; }
[JsonPropertyName(&quot;locked&quot;)] public bool Locked { get; set; }
[JsonPropertyName(&quot;lockedBy&quot;)] public object LockedBy { get; set; }
[JsonPropertyName(&quot;lockedAt&quot;)] public object LockedAt { get; set; }
[JsonPropertyName(&quot;upvotes&quot;)] public int Upvotes { get; set; }
[JsonPropertyName(&quot;downvotes&quot;)] public int Downvotes { get; set; }
[JsonPropertyName(&quot;hotness&quot;)] public object Hotness { get; set; }
[JsonPropertyName(&quot;createdAt&quot;)] public DateTime CreatedAt { get; set; }
[JsonPropertyName(&quot;editedAt&quot;)] public object EditedAt { get; set; }
[JsonPropertyName(&quot;lastActivityAt&quot;)] public DateTime LastActivityAt { get; set; }
[JsonPropertyName(&quot;deleted&quot;)] public bool Deleted { get; set; }
[JsonPropertyName(&quot;deletedAt&quot;)] public object DeletedAt { get; set; }
[JsonPropertyName(&quot;deletedContent&quot;)] public bool DeletedContent { get; set; }
[JsonPropertyName(&quot;noComments&quot;)] public int NoComments { get; set; }
[JsonPropertyName(&quot;comments&quot;)] public object Comments { get; set; }
[JsonPropertyName(&quot;commentsNext&quot;)] public object CommentsNext { get; set; }
[JsonPropertyName(&quot;userVoted&quot;)] public bool UserVoted { get; set; }
[JsonPropertyName(&quot;userVotedUp&quot;)] public bool? UserVotedUp { get; set; }
}
[JsonObject]
public class Root
{
[JsonPropertyName(&quot;posts&quot;)] public List&lt;Post&gt; Posts { get; set; }
[JsonPropertyName(&quot;next&quot;)] 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 () =&gt; await LoadPosts());
}
private async Task LoadPosts()
{
var url = $&quot;https://discuit.net/api/posts&quot;;
var client = new HttpClient();
var response = await client.GetAsync(url);
var successCode = await client.GetAsync(url);
// validate connection
if (successCode.IsSuccessStatusCode)
{
Console.WriteLine(&quot;-----------------------------------&quot;);
Console.WriteLine(&quot;Code 200 -  Successful Connection to REST API&quot;);
Console.WriteLine(&quot;-----------------------------------&quot;);
var data = await response.Content.ReadAsStringAsync();
var options = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true,
};
var posts = JsonSerializer.Deserialize&lt;Posts&gt;(data, options);
Console.WriteLine(&quot;-----------------------------------&quot;);
Console.WriteLine(&quot;Data: &quot; + data);
Console.WriteLine(&quot;Posts: &quot; + posts);
Console.WriteLine(&quot;-----------------------------------&quot;);
var Type = posts.Type;
var Username = posts.Username;
var CommunityName = posts.CommunityName;
var Title = posts.Title;
var Body = posts.Body;    
}
else
{
Console.WriteLine(&quot;Error connecting to API&quot;);
}
}

}

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"
>

&lt;ListView ItemsSource=&quot;{Binding LoadPostsCommand}&quot;&gt;
&lt;ListView.Header&gt;
&lt;VerticalStackLayout
Spacing=&quot;25&quot;
Padding=&quot;30,0&quot;
VerticalOptions=&quot;Center&quot;&gt;
&lt;Button 
x:Name=&quot;UpdateBtn&quot;
Text=&quot;Load Posts&quot;
Command=&quot;{Binding LoadPostsCommand}&quot;
Margin=&quot;10&quot;
/&gt;
&lt;/VerticalStackLayout&gt;
&lt;/ListView.Header&gt;
&lt;ListView.ItemTemplate&gt;
&lt;DataTemplate&gt;
&lt;TextCell Text=&quot;{Binding Title}&quot; Detail=&quot;{Binding Body}&quot; /&gt;
&lt;/DataTemplate&gt;
&lt;/ListView.ItemTemplate&gt;
&lt;/ListView&gt;

</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 = &quot;&quot;)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
protected bool SetProperty&lt;TValue&gt;(ref TValue backingField, TValue value, [CallerMemberName] string propertyName = &quot;&quot;)
{
if (Comparer&lt;TValue&gt;.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&lt;Root&gt;(data, options);

then use Data.Posts as your ItemsSource

&lt;ListView ItemsSource=&quot;{Binding Data.Posts}&quot;&gt;

huangapple
  • 本文由 发表于 2023年7月28日 05:09:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/76783426.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定