将项目绑定到ListView

时间:2016-06-22 12:40:27

标签: c# xamarin xamarin.forms

我正在尝试在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>

1 个答案:

答案 0 :(得分:2)

看起来你有几个问题,虽然我之前没有搞过无限滚动。要回答您的问题,您不需要绑定DataTemplate,看起来确切如此。

  1. 在您的XAML中指定ItemsSource="{Binding}",但在您的代码隐藏中设置listview.ItemsSource = books;,取消原始绑定。我建议您在代码隐藏中注释掉该行,然后留在XAML行中。

  2. 您没有等待LoadItems();。您应该将LoadItems();移至OnAppearing(),以便等待它。

  3. 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)); }
    }
    }
    
  4. 执行上述操作允许Books通知UI它已更改,以便UI更新。您还应将Books指定为ObservableCollection<>而不是IList<>

    1. 建议,我会在listview.ItemAppearing中附加ContentPage.OnAppearing()方法,然后删除ContentPage.OnDisappearing()中的事件处理程序。这样可以防止内存泄漏,应该对任何有意义的事件处理进行操作。这将要求您将ItemAppearing lambda代码放入自己的方法
    2. 在此之后,如果它仍然不适合你,请告诉我。

      编辑:忘记了ViewModel的PropertyChanged事件。请在顶部再次查看ViewModel代码。