为什么此 ListView 不与 ObservableCollection 元素绑定?
Why this ListView is not binding with ObservableCollection elements?
我正在尝试将 ListView 与可观察的集合数据绑定,但它仍然是空的。我有一些断点,可以看到 ListaProfissionais(Observable collection) 已正确填充。下面你可以看到我的 .cs 和 .xaml 代码(重要的部分)。有人看到这里出了什么问题吗?
using System.ComponentModel;
public class Profissionais : INotifyPropertyChanged
{
private string id;
public string Id
{
get { return this.id; }
set
{
if (this.id != value)
{
this.id = value;
this.NotifyPropertyChanged("Id");
}
}
}
private string categoria;
public string Categoria
{
get { return this.categoria; }
set
{
if (this.categoria != value)
{
this.categoria = value;
this.NotifyPropertyChanged("Categoria");
}
}
}
private string titulo;
public string Titulo
{
get { return this.titulo; }
set
{
if (this.titulo != value)
{
this.titulo = value;
this.NotifyPropertyChanged("Titulo");
}
}
}
private string fotoperfil;
public string FotoPerfil
{
get { return this.fotoperfil; }
set
{
if (this.fotoperfil != value)
{
this.fotoperfil = value;
this.NotifyPropertyChanged("FotoPerfil");
}
}
}
private string endereco;
public string Endereco
{
get { return this.endereco; }
set
{
if (this.endereco != value)
{
this.endereco = value;
this.NotifyPropertyChanged("Endereco");
}
}
}
private string distancia;
public string Distancia
{
get { return this.distancia; }
set
{
if (this.distancia != value)
{
this.distancia = value;
this.NotifyPropertyChanged("Distancia");
}
}
}
private string sexo;
public string Sexo
{
get { return this.sexo; }
set
{
if (this.sexo != value)
{
this.sexo = value;
this.NotifyPropertyChanged("Sexo");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string propName)
{
if (this.PropertyChanged != null)
this.PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
public static ObservableCollection<Profissionais> ListaProfissionais = new ObservableCollection<Profissionais>();
try
{
using (WebClient client = new WebClient())
{
Uri uri = new Uri("xxxx.xxxxx.php");
byte[] retorno = await client.UploadValuesTaskAsync(uri, DataSend);
string resultado = System.Text.Encoding.UTF8.GetString(retorno);
ListaProfissionais = JsonConvert.DeserializeObject<ObservableCollection<Profissionais>>(resultado);
}
}
catch
{
throw;
}
finally
{
ListViewProfissionais.ItemsSource = ListaProfissionais;
// crashes here but I can see that ItemsSource has the 4 elements as expected
}
我的XAML:
<ListView x:Name="ListViewProfissionais" x:FieldModifier="public static" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" VerticalScrollBarVisibility="Never" HorizontalScrollBarVisibility="Never" BackgroundColor="Transparent" SeparatorColor="Transparent">
<ListView.ItemTemplate>
<DataTemplate>
<Frame HasShadow="True" CornerRadius="5" HeightRequest="215" Margin="8" Padding="4" BackgroundColor="White">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="15"></RowDefinition>
<RowDefinition Height="25"></RowDefinition>
<RowDefinition Height="105"></RowDefinition>
<RowDefinition Height="25"></RowDefinition>
<RowDefinition Height="25"></RowDefinition>
</Grid.RowDefinitions>
<Label Text="{Binding Categoria}" TextColor="#8e8e8e" FontSize="10" Grid.Column="0" Grid.Row="0" VerticalOptions="StartAndExpand" HorizontalOptions="StartAndExpand" Margin="2,0,0,0"></Label>
<Label Text="{Binding Titulo}" FontAttributes="Bold" TextColor="#337760" FontSize="14" Grid.Column="0" Grid.Row="1" VerticalOptions="StartAndExpand" HorizontalOptions="StartAndExpand" Margin="2,0,0,0"></Label>
<Frame Grid.Column="0" Grid.Row="2" BackgroundColor="Transparent" CornerRadius="4" Padding="0" Margin="0">
<Image Source="{Binding FotoPerfil}" HorizontalOptions="FillAndExpand" Aspect="AspectFill" VerticalOptions="FillAndExpand" />
</Frame>
<Label Text="{Binding Endereco}" TextColor="#8e8e8e" FontSize="10" Grid.Column="0" Grid.Row="3" VerticalOptions="EndAndExpand" HorizontalOptions="StartAndExpand"></Label>
<Label Text="" Grid.Column="0" Grid.Row="4" FontSize="10" HorizontalOptions="StartAndExpand" TextColor="#ff9000" Padding="0,6,0,0">
<Label.FontFamily>
<OnPlatform x:TypeArguments="x:String" Android="Font-Awesome-Free-Solid.otf#FontAwesome5Free-Solid" iOS="FontAwesome5Free-Solid" />
</Label.FontFamily>
</Label>
<Label Text="{Binding Distancia}" TextColor="#ff9000" FontSize="10" Grid.Column="0" Grid.Row="4" VerticalOptions="Center" HorizontalOptions="StartAndExpand" Margin="10,0,0,0"></Label>
</Grid>
</Frame>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
它崩溃并显示消息 "System.InvalidCastException: Specified cast is not valid."。见下文:
System.InvalidCastException: Specified cast is not valid.
at at (wrapper castclass) System.Object.__castclass_with_cache(object,intptr,intptr)
at Xamarin.Forms.Internals.TemplatedItemsList`2[TView,TItem].ActivateContent (System.Int32 index, System.Object item) [0x00000] in D:\a\s\Xamarin.Forms.Core\TemplatedItemsList.cs:534
at Xamarin.Forms.Internals.TemplatedItemsList`2[TView,TItem].CreateContent (System.Int32 index, System.Object item, System.Boolean insert) [0x00000] in D:\a\s\Xamarin.Forms.Core\TemplatedItemsList.cs:543
at Xamarin.Forms.Internals.TemplatedItemsList`2[TView,TItem].GetOrCreateContent (System.Int32 index, System.Object item) [0x00023] in D:\a\s\Xamarin.Forms.Core\TemplatedItemsList.cs:602
at Xamarin.Forms.Internals.TemplatedItemsList`2[TView,TItem].get_Item (System.Int32 index) [0x00000] in D:\a\s\Xamarin.Forms.Core\TemplatedItemsList.cs:337
at Xamarin.Forms.Platform.Android.ListViewAdapter.GetCellsFromPosition (System.Int32 position, System.Int32 take) [0x0003b] in D:\a\s\Xamarin.Forms.Platform.Android\Renderers\ListViewAdapter.cs:539
at Xamarin.Forms.Platform.Android.ListViewAdapter.GetCellForPosition (System.Int32 position) [0x00000] in D:\a\s\Xamarin.Forms.Platform.Android\Renderers\ListViewAdapter.cs:454
at Xamarin.Forms.Platform.Android.ListViewAdapter.GetView (System.Int32 position, Android.Views.View convertView, Android.Views.ViewGroup parent) [0x0006d] in D:\a\s\Xamarin.Forms.Platform.Android\Renderers\ListViewAdapter.cs:225
at Android.Widget.BaseAdapter.n_GetView_ILandroid_view_View_Landroid_view_ViewGroup_ (System.IntPtr jnienv, System.IntPtr native__this, System.Int32 position, System.IntPtr native_convertView, System.IntPtr native_parent) [0x0001a] in <11f101b564894ca7af6c482ddc51c698>:0
at at (wrapper dynamic-method) Android.Runtime.DynamicMethodNameCounter.74(intptr,intptr,int,intptr,intptr)
我认为您必须通知 属性 已更改,例如为您的 class 实施 INotifyPropertyChanged 接口。
此外,我看不到是否设置了 DataContext。
这里有一个很好的简单示例 https://www.wpf-tutorial.com/data-binding/responding-to-changes/
更新 - 2020 年 1 月 25 日
我有时间再次检查您的代码,发现您将模板直接放在 DataTemplate 中(这在 ListView 中是不可能的)。你已经 post 你自己找到了这个(干得好!)。
我将要为您使用的修复程序留在这里,指出几件事:
XAML
<?xml version="1.0" encoding="utf-8"?>
<ContentPage
x:Name="myPage"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="Playground.MainPage">
<ListView
ItemsSource="{Binding ListaProfissionais, Source={x:Reference myPage}}"
x:Name="ListViewProfissionais" HorizontalOptions="FillAndExpand"
HasUnevenRows="True"
VerticalOptions="FillAndExpand"
VerticalScrollBarVisibility="Never"
HorizontalScrollBarVisibility="Never"
BackgroundColor="Transparent"
SeparatorColor="Transparent">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Frame HasShadow="True" CornerRadius="5" HeightRequest="215" Margin="8" Padding="4" BackgroundColor="White">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="15"></RowDefinition>
<RowDefinition Height="25"></RowDefinition>
<RowDefinition Height="105"></RowDefinition>
<RowDefinition Height="25"></RowDefinition>
<RowDefinition Height="25"></RowDefinition>
</Grid.RowDefinitions>
<Label Text="{Binding Categoria}" TextColor="#8e8e8e" FontSize="10" Grid.Column="0" Grid.Row="0" VerticalOptions="StartAndExpand" HorizontalOptions="StartAndExpand" Margin="2,0,0,0"></Label>
<Label Text="{Binding Titulo}" FontAttributes="Bold" TextColor="#337760" FontSize="14" Grid.Column="0" Grid.Row="1" VerticalOptions="StartAndExpand" HorizontalOptions="StartAndExpand" Margin="2,0,0,0"></Label>
<Frame Grid.Column="0" Grid.Row="2" BackgroundColor="Transparent" CornerRadius="4" Padding="0" Margin="0">
<Image Source="{Binding FotoPerfil}" HorizontalOptions="FillAndExpand" Aspect="AspectFill" VerticalOptions="FillAndExpand" />
</Frame>
<Label Text="{Binding Endereco}" TextColor="#8e8e8e" FontSize="10" Grid.Column="0" Grid.Row="3" VerticalOptions="EndAndExpand" HorizontalOptions="StartAndExpand"></Label>
<Label Text="" Grid.Column="0" Grid.Row="4" FontSize="10" HorizontalOptions="StartAndExpand" TextColor="#ff9000" Padding="0,6,0,0">
<Label.FontFamily>
<OnPlatform x:TypeArguments="x:String" Android="Font-Awesome-Free-Solid.otf#FontAwesome5Free-Solid" iOS="FontAwesome5Free-Solid" />
</Label.FontFamily>
</Label>
<Label Text="{Binding Distancia}" TextColor="#ff9000" FontSize="10" Grid.Column="0" Grid.Row="4" VerticalOptions="Center" HorizontalOptions="StartAndExpand" Margin="10,0,0,0"></Label>
</Grid>
</Frame>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage>
隐藏代码:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
namespace Playground
{
// Learn more about making custom code visible in the Xamarin.Forms previewer
// by visiting https://aka.ms/xamarinforms-previewer
[DesignTimeVisible(false)]
public partial class MainPage : ContentPage
{
public class Profissionais
{
public string Id { get; set; }
public string Categoria { get; set; }
public string Titulo { get; set; }
public string FotoPerfil { get; set; }
public string Endereco { get; set; }
public string Distancia { get; set; }
public string Sexo { get; set; }
}
private ObservableCollection<Profissionais> _listaProfissionais;
public ObservableCollection<Profissionais> ListaProfissionais
{
get => _listaProfissionais;
set
{
_listaProfissionais = value;
OnPropertyChanged(nameof(ListaProfissionais));
}
}
public MainPage()
{
InitializeComponent();
ListaProfissionais = new ObservableCollection<Profissionais>();
}
private async Task Call()
{
// Simulating a call to the "API" and add a new element each 2 seconds
for (int i = 0; i < 10; i++)
{
ListaProfissionais.Add(new Profissionais { Titulo = $"Professional {i}" });
await Task.Delay(2000);
}
}
protected override void OnAppearing()
{
base.OnAppearing();
// Call the "API" when everything is ready
Task.Factory.StartNew(Call);
}
}
}
这里,如您所见,Class Professionais 不需要继承INotifyPropertyChanged。您需要通知绑定引擎的唯一 属性 是您的 collection。 ContentPage 已经有一个您可以使用的 OnPropertyChanged 方法。之后,每次添加新元素时,您的 ListView 不仅会监听 属性 的变化,还会监听 collection 本身。
希望对您有所帮助!
旧
假设您正尝试从后面的代码绑定 属性 ListaProfissionais
:
方法 1(不是一个好的做法):
您必须将 ListaProfissionais
添加到 class 的 BindingContext
属性。您可以按如下方式处理:
... assuming you already called your API ...
ListaProfissionais = JsonConvert.DeserializeObject<ObservableCollection<Profissionais>>(resultado);
BindingContext = ListaProfissionais;
在你的 XAML 而不是 ItemsSource="{Binding ListaProfissionais}"
上使用 ItemSource="{Binding BindingContext}"
方法 2(更好的方法):
在 XAML 页面中为 class (Name="listPage") 设置一个名称。在您的 ListView 中,您可以执行以下操作:
ItemsSource="{Binding ListaProfissionais, Source='{x:Reference listPage}'}"
注意:稍后我会测试这个。
- 将 INotifyPropertyChanged 接口添加到您的 cs 文件并实现其方法。
将 ListaProfissionais 更改为 属性,如下所示:
private ObservableCollection<Profissionais> _listaProfissionais;
public ObservableCollection<Profissionais> ListaProfissionais
{
get => _listaProfissionais;
set
{
_listaProfissionais = value;
// This should be the method implemented by INotifyPropertyChanged.
OnPropertyChanged(nameof(ListaProfissionais);
}
}
备注:
如果您不通知绑定引擎 属性 已更改,列表将不会通知 ListView。这样,我们确保 ListView 的绑定上下文正在侦听来自 ListProfessionais 的 属性 更改。
希望对您有所帮助。
找到了问题的根源。原来是在xaml,不知道为什么,Grid标签不能直接在DataTemplate里面,必须在ViewCell标签里面,我只加了一个ViewCell,现在可以正常使用了。
我正在尝试将 ListView 与可观察的集合数据绑定,但它仍然是空的。我有一些断点,可以看到 ListaProfissionais(Observable collection) 已正确填充。下面你可以看到我的 .cs 和 .xaml 代码(重要的部分)。有人看到这里出了什么问题吗?
using System.ComponentModel;
public class Profissionais : INotifyPropertyChanged
{
private string id;
public string Id
{
get { return this.id; }
set
{
if (this.id != value)
{
this.id = value;
this.NotifyPropertyChanged("Id");
}
}
}
private string categoria;
public string Categoria
{
get { return this.categoria; }
set
{
if (this.categoria != value)
{
this.categoria = value;
this.NotifyPropertyChanged("Categoria");
}
}
}
private string titulo;
public string Titulo
{
get { return this.titulo; }
set
{
if (this.titulo != value)
{
this.titulo = value;
this.NotifyPropertyChanged("Titulo");
}
}
}
private string fotoperfil;
public string FotoPerfil
{
get { return this.fotoperfil; }
set
{
if (this.fotoperfil != value)
{
this.fotoperfil = value;
this.NotifyPropertyChanged("FotoPerfil");
}
}
}
private string endereco;
public string Endereco
{
get { return this.endereco; }
set
{
if (this.endereco != value)
{
this.endereco = value;
this.NotifyPropertyChanged("Endereco");
}
}
}
private string distancia;
public string Distancia
{
get { return this.distancia; }
set
{
if (this.distancia != value)
{
this.distancia = value;
this.NotifyPropertyChanged("Distancia");
}
}
}
private string sexo;
public string Sexo
{
get { return this.sexo; }
set
{
if (this.sexo != value)
{
this.sexo = value;
this.NotifyPropertyChanged("Sexo");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string propName)
{
if (this.PropertyChanged != null)
this.PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
public static ObservableCollection<Profissionais> ListaProfissionais = new ObservableCollection<Profissionais>();
try
{
using (WebClient client = new WebClient())
{
Uri uri = new Uri("xxxx.xxxxx.php");
byte[] retorno = await client.UploadValuesTaskAsync(uri, DataSend);
string resultado = System.Text.Encoding.UTF8.GetString(retorno);
ListaProfissionais = JsonConvert.DeserializeObject<ObservableCollection<Profissionais>>(resultado);
}
}
catch
{
throw;
}
finally
{
ListViewProfissionais.ItemsSource = ListaProfissionais;
// crashes here but I can see that ItemsSource has the 4 elements as expected
}
我的XAML:
<ListView x:Name="ListViewProfissionais" x:FieldModifier="public static" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" VerticalScrollBarVisibility="Never" HorizontalScrollBarVisibility="Never" BackgroundColor="Transparent" SeparatorColor="Transparent">
<ListView.ItemTemplate>
<DataTemplate>
<Frame HasShadow="True" CornerRadius="5" HeightRequest="215" Margin="8" Padding="4" BackgroundColor="White">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="15"></RowDefinition>
<RowDefinition Height="25"></RowDefinition>
<RowDefinition Height="105"></RowDefinition>
<RowDefinition Height="25"></RowDefinition>
<RowDefinition Height="25"></RowDefinition>
</Grid.RowDefinitions>
<Label Text="{Binding Categoria}" TextColor="#8e8e8e" FontSize="10" Grid.Column="0" Grid.Row="0" VerticalOptions="StartAndExpand" HorizontalOptions="StartAndExpand" Margin="2,0,0,0"></Label>
<Label Text="{Binding Titulo}" FontAttributes="Bold" TextColor="#337760" FontSize="14" Grid.Column="0" Grid.Row="1" VerticalOptions="StartAndExpand" HorizontalOptions="StartAndExpand" Margin="2,0,0,0"></Label>
<Frame Grid.Column="0" Grid.Row="2" BackgroundColor="Transparent" CornerRadius="4" Padding="0" Margin="0">
<Image Source="{Binding FotoPerfil}" HorizontalOptions="FillAndExpand" Aspect="AspectFill" VerticalOptions="FillAndExpand" />
</Frame>
<Label Text="{Binding Endereco}" TextColor="#8e8e8e" FontSize="10" Grid.Column="0" Grid.Row="3" VerticalOptions="EndAndExpand" HorizontalOptions="StartAndExpand"></Label>
<Label Text="" Grid.Column="0" Grid.Row="4" FontSize="10" HorizontalOptions="StartAndExpand" TextColor="#ff9000" Padding="0,6,0,0">
<Label.FontFamily>
<OnPlatform x:TypeArguments="x:String" Android="Font-Awesome-Free-Solid.otf#FontAwesome5Free-Solid" iOS="FontAwesome5Free-Solid" />
</Label.FontFamily>
</Label>
<Label Text="{Binding Distancia}" TextColor="#ff9000" FontSize="10" Grid.Column="0" Grid.Row="4" VerticalOptions="Center" HorizontalOptions="StartAndExpand" Margin="10,0,0,0"></Label>
</Grid>
</Frame>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
它崩溃并显示消息 "System.InvalidCastException: Specified cast is not valid."。见下文:
System.InvalidCastException: Specified cast is not valid.
at at (wrapper castclass) System.Object.__castclass_with_cache(object,intptr,intptr)
at Xamarin.Forms.Internals.TemplatedItemsList`2[TView,TItem].ActivateContent (System.Int32 index, System.Object item) [0x00000] in D:\a\s\Xamarin.Forms.Core\TemplatedItemsList.cs:534
at Xamarin.Forms.Internals.TemplatedItemsList`2[TView,TItem].CreateContent (System.Int32 index, System.Object item, System.Boolean insert) [0x00000] in D:\a\s\Xamarin.Forms.Core\TemplatedItemsList.cs:543
at Xamarin.Forms.Internals.TemplatedItemsList`2[TView,TItem].GetOrCreateContent (System.Int32 index, System.Object item) [0x00023] in D:\a\s\Xamarin.Forms.Core\TemplatedItemsList.cs:602
at Xamarin.Forms.Internals.TemplatedItemsList`2[TView,TItem].get_Item (System.Int32 index) [0x00000] in D:\a\s\Xamarin.Forms.Core\TemplatedItemsList.cs:337
at Xamarin.Forms.Platform.Android.ListViewAdapter.GetCellsFromPosition (System.Int32 position, System.Int32 take) [0x0003b] in D:\a\s\Xamarin.Forms.Platform.Android\Renderers\ListViewAdapter.cs:539
at Xamarin.Forms.Platform.Android.ListViewAdapter.GetCellForPosition (System.Int32 position) [0x00000] in D:\a\s\Xamarin.Forms.Platform.Android\Renderers\ListViewAdapter.cs:454
at Xamarin.Forms.Platform.Android.ListViewAdapter.GetView (System.Int32 position, Android.Views.View convertView, Android.Views.ViewGroup parent) [0x0006d] in D:\a\s\Xamarin.Forms.Platform.Android\Renderers\ListViewAdapter.cs:225
at Android.Widget.BaseAdapter.n_GetView_ILandroid_view_View_Landroid_view_ViewGroup_ (System.IntPtr jnienv, System.IntPtr native__this, System.Int32 position, System.IntPtr native_convertView, System.IntPtr native_parent) [0x0001a] in <11f101b564894ca7af6c482ddc51c698>:0
at at (wrapper dynamic-method) Android.Runtime.DynamicMethodNameCounter.74(intptr,intptr,int,intptr,intptr)
我认为您必须通知 属性 已更改,例如为您的 class 实施 INotifyPropertyChanged 接口。 此外,我看不到是否设置了 DataContext。 这里有一个很好的简单示例 https://www.wpf-tutorial.com/data-binding/responding-to-changes/
更新 - 2020 年 1 月 25 日
我有时间再次检查您的代码,发现您将模板直接放在 DataTemplate 中(这在 ListView 中是不可能的)。你已经 post 你自己找到了这个(干得好!)。
我将要为您使用的修复程序留在这里,指出几件事:
XAML
<?xml version="1.0" encoding="utf-8"?>
<ContentPage
x:Name="myPage"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="Playground.MainPage">
<ListView
ItemsSource="{Binding ListaProfissionais, Source={x:Reference myPage}}"
x:Name="ListViewProfissionais" HorizontalOptions="FillAndExpand"
HasUnevenRows="True"
VerticalOptions="FillAndExpand"
VerticalScrollBarVisibility="Never"
HorizontalScrollBarVisibility="Never"
BackgroundColor="Transparent"
SeparatorColor="Transparent">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Frame HasShadow="True" CornerRadius="5" HeightRequest="215" Margin="8" Padding="4" BackgroundColor="White">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="15"></RowDefinition>
<RowDefinition Height="25"></RowDefinition>
<RowDefinition Height="105"></RowDefinition>
<RowDefinition Height="25"></RowDefinition>
<RowDefinition Height="25"></RowDefinition>
</Grid.RowDefinitions>
<Label Text="{Binding Categoria}" TextColor="#8e8e8e" FontSize="10" Grid.Column="0" Grid.Row="0" VerticalOptions="StartAndExpand" HorizontalOptions="StartAndExpand" Margin="2,0,0,0"></Label>
<Label Text="{Binding Titulo}" FontAttributes="Bold" TextColor="#337760" FontSize="14" Grid.Column="0" Grid.Row="1" VerticalOptions="StartAndExpand" HorizontalOptions="StartAndExpand" Margin="2,0,0,0"></Label>
<Frame Grid.Column="0" Grid.Row="2" BackgroundColor="Transparent" CornerRadius="4" Padding="0" Margin="0">
<Image Source="{Binding FotoPerfil}" HorizontalOptions="FillAndExpand" Aspect="AspectFill" VerticalOptions="FillAndExpand" />
</Frame>
<Label Text="{Binding Endereco}" TextColor="#8e8e8e" FontSize="10" Grid.Column="0" Grid.Row="3" VerticalOptions="EndAndExpand" HorizontalOptions="StartAndExpand"></Label>
<Label Text="" Grid.Column="0" Grid.Row="4" FontSize="10" HorizontalOptions="StartAndExpand" TextColor="#ff9000" Padding="0,6,0,0">
<Label.FontFamily>
<OnPlatform x:TypeArguments="x:String" Android="Font-Awesome-Free-Solid.otf#FontAwesome5Free-Solid" iOS="FontAwesome5Free-Solid" />
</Label.FontFamily>
</Label>
<Label Text="{Binding Distancia}" TextColor="#ff9000" FontSize="10" Grid.Column="0" Grid.Row="4" VerticalOptions="Center" HorizontalOptions="StartAndExpand" Margin="10,0,0,0"></Label>
</Grid>
</Frame>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage>
隐藏代码:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
namespace Playground
{
// Learn more about making custom code visible in the Xamarin.Forms previewer
// by visiting https://aka.ms/xamarinforms-previewer
[DesignTimeVisible(false)]
public partial class MainPage : ContentPage
{
public class Profissionais
{
public string Id { get; set; }
public string Categoria { get; set; }
public string Titulo { get; set; }
public string FotoPerfil { get; set; }
public string Endereco { get; set; }
public string Distancia { get; set; }
public string Sexo { get; set; }
}
private ObservableCollection<Profissionais> _listaProfissionais;
public ObservableCollection<Profissionais> ListaProfissionais
{
get => _listaProfissionais;
set
{
_listaProfissionais = value;
OnPropertyChanged(nameof(ListaProfissionais));
}
}
public MainPage()
{
InitializeComponent();
ListaProfissionais = new ObservableCollection<Profissionais>();
}
private async Task Call()
{
// Simulating a call to the "API" and add a new element each 2 seconds
for (int i = 0; i < 10; i++)
{
ListaProfissionais.Add(new Profissionais { Titulo = $"Professional {i}" });
await Task.Delay(2000);
}
}
protected override void OnAppearing()
{
base.OnAppearing();
// Call the "API" when everything is ready
Task.Factory.StartNew(Call);
}
}
}
这里,如您所见,Class Professionais 不需要继承INotifyPropertyChanged。您需要通知绑定引擎的唯一 属性 是您的 collection。 ContentPage 已经有一个您可以使用的 OnPropertyChanged 方法。之后,每次添加新元素时,您的 ListView 不仅会监听 属性 的变化,还会监听 collection 本身。
希望对您有所帮助!
旧
假设您正尝试从后面的代码绑定 属性 ListaProfissionais
:
方法 1(不是一个好的做法):
您必须将 ListaProfissionais
添加到 class 的 BindingContext
属性。您可以按如下方式处理:
... assuming you already called your API ...
ListaProfissionais = JsonConvert.DeserializeObject<ObservableCollection<Profissionais>>(resultado);
BindingContext = ListaProfissionais;
在你的 XAML 而不是 ItemsSource="{Binding ListaProfissionais}"
上使用 ItemSource="{Binding BindingContext}"
方法 2(更好的方法):
在 XAML 页面中为 class (Name="listPage") 设置一个名称。在您的 ListView 中,您可以执行以下操作:
ItemsSource="{Binding ListaProfissionais, Source='{x:Reference listPage}'}"
注意:稍后我会测试这个。
- 将 INotifyPropertyChanged 接口添加到您的 cs 文件并实现其方法。
将 ListaProfissionais 更改为 属性,如下所示:
private ObservableCollection<Profissionais> _listaProfissionais;
public ObservableCollection<Profissionais> ListaProfissionais
{
get => _listaProfissionais;
set
{
_listaProfissionais = value;
// This should be the method implemented by INotifyPropertyChanged.
OnPropertyChanged(nameof(ListaProfissionais);
}
}
备注: 如果您不通知绑定引擎 属性 已更改,列表将不会通知 ListView。这样,我们确保 ListView 的绑定上下文正在侦听来自 ListProfessionais 的 属性 更改。
希望对您有所帮助。
找到了问题的根源。原来是在xaml,不知道为什么,Grid标签不能直接在DataTemplate里面,必须在ViewCell标签里面,我只加了一个ViewCell,现在可以正常使用了。