我正在尝试在xamarin.forms中创建无限滚动。我认为问题是,我的项目没有绑定到我的ListView。我是否必须将我的datatemplate绑定到listview。我的datatemplate包含带有文本,细节和ImageSource的imagecell。
我正在调试时,我的listview.ItemAppearing + =(发件人,e)=>从未被称为。所以我假设这是我的问题。
我正在使用带有json响应的Http客户端。贝娄是我的代码:
public partial class MainPage : ContentPage
{
readonly IList<Article> books = new ObservableCollection<Article>();
readonly BookManager manager = new BookManager();
bool isLoading;
public MainPage()
{
books = new ObservableCollection<Article>();
var listview = new ListView();
listview.ItemsSource = books;
listview.ItemAppearing += (sender, e) =>
{
if (isLoading || books.Count == 0)
return;
//hit bottom!
if (e.Item == books[books.Count - 1])
{
LoadItems();
}
};
LoadItems();
BindingContext = books;
InitializeComponent();
}
我的LoadItems方法:
public async void LoadItems()
{
//simulator delayed load
var bookCollection = await manager.GetAll();
foreach (Article book in bookCollection.articles)
{
books.Add(book);
}
}
和我的xamlpage
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="BookClient.MainPage"
Title="Library Books">
<ContentPage.ToolbarItems>
<ToolbarItem Text="Add New" Icon="ic_action_new.png" Clicked="OnAddNewBook" />
<ToolbarItem Text="Refresh" Icon="ic_autorenew.png" Clicked="OnRefresh" />
</ContentPage.ToolbarItems>
<ListView
ItemsSource="{Binding}"
ItemTapped="OnEditBook">
<ListView.ItemTemplate>
<DataTemplate>
<ImageCell
Text="{Binding id, StringFormat='ID= {0}'}" Detail="{Binding content}" ImageSource="{Binding images.image_intro}">
<ImageCell.ContextActions>
<MenuItem Clicked="OnDeleteBook"
CommandParameter="{Binding}"
Text="Delete" IsDestructive="True" />
</ImageCell.ContextActions>
</ImageCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage>
答案 0 :(得分:2)
看起来你有几个问题,虽然我之前没有搞过无限滚动。要回答您的问题,您不需要绑定DataTemplate
,看起来确切如此。
在您的XAML中指定ItemsSource="{Binding}"
,但在您的代码隐藏中设置listview.ItemsSource = books;
,取消原始绑定。我建议您在代码隐藏中注释掉该行,然后留在XAML行中。
您没有等待LoadItems();
。您应该将LoadItems();
移至OnAppearing()
,以便等待它。
将books
属性移动到ViewModel中,然后让ViewModel继承自INotifyPropertyChanged
并将ViewModel设置为BindingContext
。这会使您ListView.ItemSource
更改为ItemsSource="{Binding Books}"
。所以你的ViewModel将成为
public class BooksViewModel : INotifyPropertyChanged {
public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
private ObservableCollection<Article> _books;
public ObservableCollection<Article> Books {
get { return _books ?? (_books = new ObservableCollection<Article>()); }
set {
if(_books != value) {
_books = value;
OnPropertyChanged();
}
}
}
public async void LoadItems()
{
//simulator delayed load
var bookCollection = await manager.GetAll();
foreach (Article book in bookCollection.articles)
{
books.Add(book);
}
}
protected virtual void OnPropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) {
System.ComponentModel.PropertyChangedEventHandler handler = PropertyChanged;
if(handler != null) { handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); }
}
}
执行上述操作允许Books
通知UI它已更改,以便UI更新。您还应将Books
指定为ObservableCollection<>
而不是IList<>
listview.ItemAppearing
中附加ContentPage.OnAppearing()
方法,然后删除ContentPage.OnDisappearing()
中的事件处理程序。这样可以防止内存泄漏,应该对任何有意义的事件处理进行操作。这将要求您将ItemAppearing
lambda代码放入自己的方法在此之后,如果它仍然不适合你,请告诉我。
编辑:忘记了ViewModel的PropertyChanged
事件。请在顶部再次查看ViewModel代码。