Xamarin.Forms ListView绑定问题



我们是Xamarin的新手。我们在将web服务的响应数据绑定到ListView时遇到问题。

我们进行了调试,可以看到web服务成功地用数据进行了响应,但它从未被填充。

有什么想法吗?

这一定是我们错过的一件小事。我们已经设法用其他视图(在项目的其他部分(显示了数据中的单个条目,但没有显示在IEnumerable<>List<>

这是代码:

视图-RoundsPage.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"
xmlns:viewModels="clr-namespace:AthlosifyMobile.ViewModels"
x:Class="AthlosifyMobile.Views.RoundsPage">
<ContentPage.BindingContext>
<viewModels:RoundsViewModel />
</ContentPage.BindingContext>
<StackLayout>
<Entry Text="{Binding AccessToken}" />
<Button Command="{Binding GetRoundsCommand}" Text="Get all rounds" />
<Label Text="Rounds: "></Label>
<ListView ItemsSource="{Binding Rounds}" HasUnevenRows="true"  >
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Horizontal">
<Label Text="Round 1:"></Label>
<Label Text="{Binding Name}"></Label>
<Label Text="{Binding DailyHandicap}"></Label>
<Label Text="{Binding PlayedUTC}"></Label>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage>`

ViewModel-圆形ViewModel.cs:

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Text;
using System.Windows.Input;
using AthlosifyMobile.Annotations;
using Xamarin.Forms;
using AthlosifyMobile.Services;
using AthlosifyMobile.Models;
namespace AthlosifyMobile.ViewModels
{ 
public class RoundsViewModel : INotifyPropertyChanged
{
ApiServices _apiServices = new ApiServices();
public event PropertyChangedEventHandler PropertyChanged;
private IEnumerable<Round> _rounds;
public string AccessToken { get; set; }
public IEnumerable<Round> Rounds
{
get
{
return _rounds;
}
set
{
_rounds = value;
OnPropertyChanged();
}
}
public ICommand GetRoundsCommand
{
get
{
return new Command(async() =>
{
Rounds = await _apiServices.GetRoundsAsync(AccessToken);
});
}
}
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}

模型-Course.cs

using System;
using System.Collections.Generic;
using System.Text;
namespace AthlosifyMobile.Models
{
public class Round : EntityBase
{
public Guid RoundID { get; set; }
public Guid UserID  { get; set; }
public Guid RoundCategoryID { get; set; }
public Guid CourseID { get; set; }
public string Name { get; set; }
public string Notes { get; set; }
public int DailyHandicap { get; set; }
public DateTime PlayedUTC { get; set; }
public RoundCategory RoundCategory { get; set; }
public Course Course { get; set; }
public ICollection<RoundHole> RoundHoles { get; set; }
}   
public abstract class EntityBase
{
public DateTime CreatedUTC { get; set; }
public DateTime LastModifiedUTC { get; set; }
}
}

服务-apiservices.cs:

using AthlosifyMobile.Models;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
namespace AthlosifyMobile.Services
{
public async Task<IEnumerable<Round>> GetRoundsAsync(string accessToken)
{
var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
var json = await client.GetStringAsync("http://localhost:5609/api/Rounds");
var list = JsonConvert.DeserializeObject<IEnumerable<Round>>(json);
return list;
}
}
}

您需要诊断这是将视图连接到ViewModel的问题,还是您的数据服务工作不正常。不管怎样,你都应该做一些事情来解决这个问题!

首先,您使用的是IEnumerable,而应该使用ObservableCollection<T>。对于绑定的列表视图,应该始终使用ObservableCollection<T>。这在xamarin文档中有解释(当内容发生更改和更新时,它们会自动通知视图(。

所以你应该做出这个改变:

public ObservableCollection<Round> Rounds { get; }

接下来,您应该验证绑定是否正确。如果你不熟悉xamarin,我不建议你直接使用实时数据的方法。首先,您应该尝试将一些静态对象添加到视图模型中,并尝试绑定它们!

断开API代码的连接,并调用一个创建某些Round对象的方法。这里有一个示例方法(在设计ListViewsUI时,我一直使用这样的方法(。

public RoundsViewModel()
{
Rounds = CreateSampleData();
}
private ObservableCollection<Round> CreateSampleData()
{
ObservableCollection<Round> dummyData = new ObservableCollection<Round>();
dummyData.Add(new Round() { Name="User", handicap=1, PlayedUTC=DateTime.Now });
dummyData.Add(new Round() { Name="User", handicap=1, PlayedUTC=DateTime.Now });
dummyData.Add(new Round() { Name="User", handicap=1, PlayedUTC=DateTime.Now });
return dummyData;
}

此时,您将在ListView中看到项目,这意味着您的API代码/INotifyPropertyChanged的实现存在问题。如果您没有看到任何内容,则可能存在绑定问题,需要验证您的视图是否实际连接到视图模型。

Mvvm帮助

看到这些代码让我为你感到非常抱歉,你肯定应该考虑使用MVVM助手,如Prism或MVVMCross。我个人使用Prism,它提供了所有ViewModels都继承的ViewModelBase。这意味着所有的INotifyPropertyChanged代码都被隐藏起来(没有样板(。它还有一个依赖性服务,这意味着将视图连接到视图模型就像在app.cs.中注册一样简单

如果你对棱镜感兴趣,请与Brian Lagunas一起观看这段视频,看看棱镜能为你做些什么!

更新:除了Prism之外,现在还有一些有用的库可以帮助MVVM。Refracted.MVMHelpers和Xamarin.CommunityToolkit都包含一个基本对象:ObservableRangeCollection

ALL使用ObservableCollection的代码应替换为ObservableRangeCollection,它是一个重要对象,目前确实属于microsoft维护的命名空间。它为更新更大的集合创造了性能优势&在更新ObservableCollection时减少了对大量样板的需求

最新更新