【问题标题】:Bind items to a ListView将项目绑定到 ListView
【发布时间】:2016-08-24 21:15:36
【问题描述】:

我正在尝试在 xamarin.forms 中创建无限滚动。我认为问题在于,我的项目没有绑定到我的 ListView。我是否必须将我的数据模板绑定到列表视图。我的数据模板包含带有文本、详细信息和 ImageSource 的 imagecell。

在调试时,我的 listview.ItemAppearing += (sender, 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>

【问题讨论】:

  • 如果您在 XAML 中创建 ListView,则无需在后面的代码中创建它。您还在两个不同的地方指定绑定。

标签: c# xamarin xamarin.forms


【解决方案1】:

看起来你有几个问题,虽然我以前没有搞过无限滚动。要回答你的问题,你不需要绑定你的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)); }
    }
    }
    

执行上述操作允许Books 通知 UI 它已更改,以便 UI 将更新。您还应该将Books 指定为ObservableCollection&lt;&gt; 而不是IList&lt;&gt;

  1. 一个建议,我会在ContentPage.OnAppearing() 中将一个方法附加到listview.ItemAppearing,然后删除ContentPage.OnDisappearing() 中的事件处理程序。这将防止内存泄漏,并且应该对任何有意义的事件处理进行。这将要求您将 ItemAppearing lambda 代码放入自己的方法中

让我知道在此之后它是否仍然不适合你。

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

【讨论】:

  • 谢谢,我明天看看再告诉你。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多