.NET MAUI ListView 无法呈现数据。

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

.NET MAUI ListView not rendering data

问题

I am trying to show the medicineList data in the ListPage.xaml using ListView. I have checked the documentation but I don't find anything noticeable. I have looked at this doc and tried to follow it. But it is not working.

This is ListPage.xaml.cs

using MedicineAlert.Data;
using System.Text.Json;

namespace MedicineAlert.Pages;

public partial class ListPage : ContentPage
{
    public List<MedicineData> MedicineList { get; set; }
    public ListPage()
	{
		InitializeComponent();
        // Retrieve the app's local data directory path
        string localDataDirPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
        // Combine the local data directory path with your desired subdirectory
        string dbFolderPath = Path.Combine(localDataDirPath, "DB");
        string filePath = Path.Combine(dbFolderPath, "data.json");

        if(File.Exists(filePath))
        {
            string json = File.ReadAllText(filePath);
            MedicineList = JsonSerializer.Deserialize<List<MedicineData>>(json);
        }
    }
}

This is ListPage.xaml

<?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="MedicineAlert.Pages.ListPage"
             Title="ListPage"
             x:Name="MedicinesPage">
    <StackLayout>
        <ListView 
            ItemsSource="{Binding MedicineList, Source={x:Reference MedicinesPage}}"
        >
            <ListView.ItemTemplate>
                <DataTemplate>
                    <TextCell
                        Text="{Binding MedicineName}"
                    />
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </StackLayout>
</ContentPage>

And this is AppShell.xaml

<?xml version="1.0" encoding="UTF-8" ?>
<Shell
    x:Class="MedicineAlert.AppShell"
    xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:views="clr-namespace:MedicineAlert.Pages"
>
    <TabBar>
        <Tab
            Title="Add"
            Icon="add.png"
        >
            <ShellContent
                Title="Home"
                ContentTemplate="{DataTemplate views:AddPage}"
                Route="AddPage" 
            />
        </Tab>

        <Tab 
            Title="List"
            Icon="list.png"
        >
            <ShellContent
                Title="List"
                ContentTemplate="{DataTemplate views:ListPage}"
                Route="ListPage" 
            />
        </Tab>
    </TabBar>
</Shell>

The ListView in ListPage is not rendering. What could be the problem?

英文:

I am trying to show the medicineList data in the ListPage.xaml using ListView. I have checked the documentation but I don't find anything noticeable. I have looked at this doc and tried to follow it. But it is not working.

This is ListPage.xaml.cs

using MedicineAlert.Data;
using System.Text.Json;

namespace MedicineAlert.Pages;

public partial class ListPage : ContentPage
{
    public List&lt;MedicineData&gt; MedicineList { get; set; }
    public ListPage()
	{
		InitializeComponent();
        // Retrieve the app&#39;s local data directory path
        string localDataDirPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
        // Combine the local data directory path with your desired subdirectory
        string dbFolderPath = Path.Combine(localDataDirPath, &quot;DB&quot;);
        string filePath = Path.Combine(dbFolderPath, &quot;data.json&quot;);

        if(File.Exists(filePath))
        {
            string json = File.ReadAllText(filePath);
            MedicineList = JsonSerializer.Deserialize&lt;List&lt;MedicineData&gt;&gt;(json);
        }
    }
}

This is ListPage.xaml

&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&gt;
&lt;ContentPage xmlns=&quot;http://schemas.microsoft.com/dotnet/2021/maui&quot;
             xmlns:x=&quot;http://schemas.microsoft.com/winfx/2009/xaml&quot;
             x:Class=&quot;MedicineAlert.Pages.ListPage&quot;
             Title=&quot;ListPage&quot;
             x:Name=&quot;MedicinesPage&quot;&gt;
    &lt;StackLayout&gt;
        &lt;ListView 
            ItemsSource=&quot;{Binding MedicineList, Source={x:Reference MedicinesPage}}&quot;
        &gt;
            &lt;ListView.ItemTemplate&gt;
                &lt;DataTemplate&gt;
                    &lt;TextCell
                        Text=&quot;{Binding MedicineName}&quot;
                    /&gt;
                &lt;/DataTemplate&gt;
            &lt;/ListView.ItemTemplate&gt;
        &lt;/ListView&gt;
    &lt;/StackLayout&gt;
&lt;/ContentPage&gt;

And this is AppShell.xaml

&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; ?&gt;
&lt;Shell
    x:Class=&quot;MedicineAlert.AppShell&quot;
    xmlns=&quot;http://schemas.microsoft.com/dotnet/2021/maui&quot;
    xmlns:x=&quot;http://schemas.microsoft.com/winfx/2009/xaml&quot;
    xmlns:views=&quot;clr-namespace:MedicineAlert.Pages&quot;
&gt;
    &lt;TabBar&gt;
        &lt;Tab
            Title=&quot;Add&quot;
            Icon=&quot;add.png&quot;
        &gt;
            &lt;ShellContent
                Title=&quot;Home&quot;
                ContentTemplate=&quot;{DataTemplate views:AddPage}&quot;
                Route=&quot;AddPage&quot; 
            /&gt;
        &lt;/Tab&gt;

        &lt;Tab 
            Title=&quot;List&quot;
            Icon=&quot;list.png&quot;
        &gt;
            &lt;ShellContent
                Title=&quot;List&quot;
                ContentTemplate=&quot;{DataTemplate views:ListPage}&quot;
                Route=&quot;ListPage&quot; 
            /&gt;
        &lt;/Tab&gt;
    &lt;/TabBar&gt;
&lt;/Shell&gt;

The ListView in ListPage is not rendering. What could be the problem?

答案1

得分: 1

以下是已翻译的内容:

`ListView` 未渲染的原因有两个:

1. `internal List&lt;MedicineData&gt; medicineList` 是一个字段,但它应该是一个属性,因为只有属性可以在绑定表达式中使用。
2. 您的 `ItemsSource` 绑定没有指向代码后端。

首先,将字段更改为属性:

```c#
public List&lt;MedicineData&gt; MedicineList { get; }

然后,将 InitializeComponent(); 调用移到构造函数的末尾:

public ListPage()
{        
    // 检索应用程序的本地数据目录路径
    string localDataDirPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
    // 将本地数据目录路径与所需的子目录相结合
    string dbFolderPath = Path.Combine(localDataDirPath, &quot;DB&quot;);
    string filePath = Path.Combine(dbFolderPath, &quot;data.json&quot;);

    if(File.Exists(filePath))
    {
        string json = File.ReadAllText(filePath);
        MedicineList = JsonSerializer.Deserialize&lt;List&lt;MedicineData&gt;&gt;(json);
    }

    InitializeComponent();
}

这是必需的,因为在您的情况下,绑定仅会在 InitializeComponent(); 调用期间进行一次评估。

最后,根据以下方式更新 XAML,使用绑定 Source,它指向页面的名称:

<?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?>
<ContentPage xmlns=&quot;http://schemas.microsoft.com/dotnet/2021/maui&quot;
             xmlns:x=&quot;http://schemas.microsoft.com/winfx/2009/xaml&quot;
             x:Class=&quot;MedicineAlert.Pages.ListPage&quot;
             Title=&quot;ListPage&quot;
             x:Name=&quot;MedicinesPage&quot;>
    <StackLayout>
        <ListView 
            ItemsSource=&quot;{Binding MedicineList, Source={x:Reference MedicinesPage}}&quot;>
            <ListView.ItemTemplate>
                <DataTemplate>
                    <TextCell
                        Text=&quot;{Binding MedicineName}&quot;
                    />
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </StackLayout>
</ContentPage>

将页面绑定到其自己的代码后端也是一种方法,通过设置 BindingContext = this;,但在这种方法中是不必要的。

注意: 不建议在构造函数内加载数据。您可能需要重新思考您的代码设计。如果需要频繁更新 List,应该将其替换为 ObservableCollection,并使属性本身也可观察。这是MVVM 模式的常见用例。

英文:

The reason the ListView is not rendering is two-fold:

  1. The internal List&lt;MedicineData&gt; medicineList is a field, but it should be a property as only properties can be used in binding expressions
  2. Your ItemsSource binding is not pointing to the code-behind

First, change the field into a property:

public List&lt;MedicineData&gt; MedicineList { get; }

after that, move the InitializeComponent(); call to the end of the constructor:

public ListPage()
{        
    // Retrieve the app&#39;s local data directory path
    string localDataDirPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
    // Combine the local data directory path with your desired subdirectory
    string dbFolderPath = Path.Combine(localDataDirPath, &quot;DB&quot;);
    string filePath = Path.Combine(dbFolderPath, &quot;data.json&quot;);

    if(File.Exists(filePath))
    {
        string json = File.ReadAllText(filePath);
        MedicineList = JsonSerializer.Deserialize&lt;List&lt;MedicineData&gt;&gt;(json);
    }

    InitializeComponent();
}

This is required, because in your case the binding will only get evaluated once and that happens during the InitializeComponent(); call.

Finally, update the XAML as follows using a binding Source which points to the name of the page:

&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&gt;
&lt;ContentPage xmlns=&quot;http://schemas.microsoft.com/dotnet/2021/maui&quot;
             xmlns:x=&quot;http://schemas.microsoft.com/winfx/2009/xaml&quot;
             x:Class=&quot;MedicineAlert.Pages.ListPage&quot;
             Title=&quot;ListPage&quot;
             x:Name=&quot;MedicinesPage&quot;&gt;
    &lt;StackLayout&gt;
        &lt;ListView 
            ItemsSource=&quot;{Binding MedicineList, Source={x:Reference MedicinesPage}}&quot;&gt;
            &lt;ListView.ItemTemplate&gt;
                &lt;DataTemplate&gt;
                    &lt;TextCell
                        Text=&quot;{Binding MedicineName}&quot;
                    /&gt;
                &lt;/DataTemplate&gt;
            &lt;/ListView.ItemTemplate&gt;
        &lt;/ListView&gt;
    &lt;/StackLayout&gt;
&lt;/ContentPage&gt;

Binding a page to its own code behind is also an option by setting BindingContext = this;, but that's not necessary with this approach.

Note: It's not recommended to load data inside a constructor. You may want to rethink your code design here. If you need to update the List frequently, you should replace it with an ObservableCollection and make the property itself also observable. This is a common use case for the MVVM pattern.

答案2

得分: 0

以下是您代码中需要翻译的部分:

  1. 尝试将以下代码
internal List&lt;MedicineData&gt; medicineList;

替换为

public List&lt;MedicineData&gt; medicineList { get; set; }
  1. 为您的页面设置BindingContext
public partial class ListPage : ContentPage
{
    //internal List&lt;MedicineData&gt; medicineList;
    public List&lt;MedicineData&gt; medicineList { get; set; }

    public ListPage()
    {
        InitializeComponent();
        // 获取应用程序的本地数据目录路径
        string localDataDirPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
        // 将本地数据目录路径与所需的子目录相结合
        string dbFolderPath = Path.Combine(localDataDirPath, &quot;DB&quot;);
        string filePath = Path.Combine(dbFolderPath, &quot;data.json&quot;);
    
        if(File.Exists(filePath))
        {
            string json = File.ReadAllText(filePath);
            medicineList = JsonSerializer.Deserialize&lt;List&lt;MedicineData&gt;&gt;(json);
        }

        // 在此处设置BindingContext
        this.BindingContext = this;    
    }
}

注意:

您可以重新检查是否已正确获取medicineList的数据。

英文:

There are several problems in your code.

  1. Try to replace the following code
internal List&lt;MedicineData&gt; medicineList;

with

public List&lt;MedicineData&gt; medicineList { get; set; }
  1. Set the BindingContext for your page:
public partial class ListPage : ContentPage
{
    //internal List&lt;MedicineData&gt; medicineList;
    public List&lt;MedicineData&gt; medicineList { get; set; }

    public ListPage()
    {
        InitializeComponent();
        // Retrieve the app&#39;s local data directory path
        string localDataDirPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
        // Combine the local data directory path with your desired subdirectory
        string dbFolderPath = Path.Combine(localDataDirPath, &quot;DB&quot;);
        string filePath = Path.Combine(dbFolderPath, &quot;data.json&quot;);
    
        if(File.Exists(filePath))
        {
            string json = File.ReadAllText(filePath);
            medicineList = JsonSerializer.Deserialize&lt;List&lt;MedicineData&gt;&gt;(json);
        }

        // set BindingContext here
        this.BindingContext = this;    
    }
}

Note:

You can recheck if you have get the correct data for medicineList.

huangapple
  • 本文由 发表于 2023年5月29日 15:34:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/76355450.html
匿名

发表评论

匿名网友

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

确定