【问题标题】:Xamarin.Forms: ListView not Displaying in AndroidXamarin.Forms:ListView 未在 Android 中显示
【发布时间】:2016-07-31 10:04:31
【问题描述】:

美好的一天。我正在创建一个简单的 Xamarin.Forms(便携式)应用程序,它允许我创建员工记录并将其保存在 Visual Studio 的数据库中。所有记录都显示到 ListView。

当我在 UWP 上运行我的应用程序时,它运行良好。它在 ListView 上正确显示所有创建的记录。

但是当我在 Android 平台上运行它时,它并没有在 ListView 中显示任何记录。我什至尝试检查 Web API 是否返回值。我确实得到了一个价值。意思是,问题出在 Android 平台上,为什么它没有显示任何记录。

你遇到过这个问题吗?您认为这背后的原因是什么?我现在能做什么?抱歉,我只是 Xamarin 的新手。希望您能够帮助我。非常感谢。

这些是我的一些代码:

EmployeeRecordsPage.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="XamarinFormsDemo.EmployeeRecordsPage"
         xmlns:ViewModels="clr-namespace:XamarinFormsDemo.ViewModels;assembly=XamarinFormsDemo"
         xmlns:controls="clr-namespace:ImageCircle.Forms.Plugin.Abstractions;assembly=ImageCircle.Forms.Plugin.Abstractions"
         BackgroundImage="bg3.jpg"
         Title="List of Employees">


  <ContentPage.BindingContext>
    <ViewModels:MainViewModel/>
  </ContentPage.BindingContext>

  <StackLayout Orientation="Vertical">


    <ListView ItemsSource="{Binding EmployeesList}"
        HasUnevenRows="True"
        IsPullToRefreshEnabled="True"
        >
<ListView.ItemTemplate>
  <DataTemplate>
    <ViewCell>
      <Grid Padding="10" RowSpacing="10" ColumnSpacing="5">
        <Grid.RowDefinitions>
          <RowDefinition Height="Auto"/>
          <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
          <ColumnDefinition Width="Auto"/>
          <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>

        <controls:CircleImage Source="icon.png"
               HeightRequest="66"
               HorizontalOptions="CenterAndExpand"
               Aspect="AspectFill"
               WidthRequest="66"
               Grid.RowSpan="2"
               />


        <Label Grid.Column="1"
               Text="{Binding EMPLOYEE_NAME}"
               TextColor="#24e97d"
               FontSize="24"/>



      <Label Grid.Column="1"
              Grid.Row="1"
               Text="{Binding EMP_NUMBER}"
               TextColor="White"
               FontSize="18"
               Opacity="0.6"/>


        <Label Grid.Column="1"
            Grid.Row="2"
            Text="{Binding DEPT_COMP}"
             TextColor="White"
             FontSize="18"
             Opacity="0.6"/>



          </Grid>
        </ViewCell>
      </DataTemplate>
    </ListView.ItemTemplate>

  </ListView>


<StackLayout Orientation="Vertical"
         Padding="30,10,30,10"
         HeightRequest="20"
         BackgroundColor="#24e97d"
         VerticalOptions="Center"
         Opacity="0.5">
  <Label Text="© Copyright 2016   SMESOFT.COM.PH   All Rights Reserved "
         HorizontalTextAlignment="Center"
         VerticalOptions="Center"
         HorizontalOptions="Center" />
    </StackLayout>
  </StackLayout>



</ContentPage>

..

EmployeeViewModel.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using XamarinFormsDemo.Models;
using XamarinFormsDemo.Services;

namespace XamarinFormsDemo.ViewModels
{
    public class MainViewModel : INotifyPropertyChanged
    {

        private List<Employee> _employeesList;
        private Employee _selectedEmployee = new Employee();




    public List<Employee> EmployeesList
    {
        get { return _employeesList; }
        set
        {
            _employeesList = value;
            OnPropertyChanged();
        }
    }



    public MainViewModel()
    {
        InitializeDataAsync();
    }

    private async Task InitializeDataAsync()
    {
        var employeesServices = new EmployeesServices();

        EmployeesList = await employeesServices.GetEmployeesAsync();
    }


    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        var handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }

    }
}

..

EmployeesServices.cs

using Plugin.RestClient;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using XamarinFormsDemo.Models;

namespace XamarinFormsDemo.Services
{
   public class EmployeesServices
    {

    public async Task<List<Employee>> GetEmployeesAsync()
    {
        RestClient<Employee> restClient = new RestClient<Employee>();

        var employeesList = await restClient.GetAsync();

        return employeesList;

        }

    }
}

【问题讨论】:

  • 你能告诉你 MainActivity for android 吗?您是否尝试在 Xamarin 表单页面中设置断点并检查它是否被命中?
  • @user3185569 先生,我没有尝试设置断点。我还不知道怎么做。这是我的 MainActivity 代码。 pastie.org/10906729
  • 问题不在于我显示的代码。你能提供一个示例项目来运行吗?
  • @therealjohn 好的,先生。我可以给你发电子邮件,如果可以的话,我会直接发给你吗?
  • @user3185569 先生,您检查过我的代码了吗?

标签: c# xaml xamarin xamarin.forms uwp-xaml


【解决方案1】:

我认为问题在于您在获取项目后没有更新 ListView:

EmployeesList = await employeesServices.GetEmployeesAsync();

我建议使用 ObservableCollection 而不是 List。使用可观察集合,当添加或删除 ObservableCollection 中的项目时,ListView 应该会自动更新。所以而不是:

private List<Employee> _employeesList;

尝试:

private ObservableCollection<Employee> _employeesList;

或者您可以将ListView.ItemsSource 分配给null,然后在获取数据后返回List&lt;Employee&gt;

编辑:正如 Jaycee 所指出的,以下用于重置 ItemsSource 的代码不应出现在视图模型中,因为视图模型将无权访问 listView。但是刷新listView.ItemsSource 的方法是正确的。视图模型只需要让视图知道EmployeesList 已更新,然后您可以在视图后面的代码中重置listView.ItemsSource。这可以通过我能想到的几种方式来完成。例如,您可以在 ViewModel 中有一个委托,视图可以为其提供代码实现,或者视图模型可以引发视图可以订阅的事件。基本上你只需要让视图知道它需要刷新它的ListViewItemsSource。但是所有这些都可以通过使用ObservableCollection 而不是我之前提到的列表来避免。

EmployeesList = await employeesServices.GetEmployeesAsync();
listView.ItemsSource = null;
listView.ItemsSource = EmployeesList;

要执行上述操作,您必须为 ListView 指定一个名称,以便在代码中引用它。您可以在 XAML 中为 ListView 设置此名称:

<ListView 
    ItemsSource="{Binding EmployeesList}"
    HasUnevenRows="True"
    IsPullToRefreshEnabled="True"
    x:Name="listView"
>

但 ObservableCollection 将是更可取的选择。

【讨论】:

  • 先生为什么我不能访问我的 ViewModel 中的 listView,即使我在这里声明它:x:Name="listView"
  • 它将在 Xaml 页面的代码隐藏文件中可用,而不是视图模型。我不是 MVVM 专家,但据我了解,理想情况下 ViewModel 不需要了解有关视图的任何信息,因为视图 ​​ViewModel 可能用于多个视图。因此,您可能希望在加载EmployeesList 时让您的ViewModel 引发一个事件,并且您的视图代码可以订阅该事件,以便它可以重新加载listView 的ItemsSource。
  • 是的,先生,它在我后面的代码中可用。因此,因此您在这里所做的不正确:EmployeesList = await employeesServices.GetEmployeesAsync(); listView.ItemsSource = null; listView.ItemsSource = 员工列表;
  • 抱歉,我忽略了该代码在您的视图模型中。但是我的回答基本上是正确的,除了将代码放在哪里刷新listView,所以请接受它。
  • 好的先生,我会接受你的回答,没问题。我只想知道如何在我的代码中访问EmployeesList?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-02-25
  • 2020-03-15
  • 2015-12-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多