首页 > 解决方案 > 从列表中删除项目时不会触发 Xamarin.Forms Listview 的 ItemDisappearing 事件

问题描述

我是 Xamarin.Forms 的新手,我有一个带有项目源的列表视图。

ItemSourceListView 的 是一个不幸的ObserverableCollection ,当我从 中删除一个项目时,不会触发ItemSource该事件。ItemDisapperaing是的,列表项已从 Android 设备的 UI 中删除。

但是我实现了ItemAppearing并且效果很好!它触发了。

添加项目工作场景:

  1. ShopCart.Instance.AddItem(randomItem)被叫。
  2. ShopItemListView.ItemsSource用新添加的项目刷新。
  3. TotalAmount的文本以正确的数量更新。 所以调用了 ShopItem_NewItemAdded 函数!

从购物车场景中清除项目(不工作)

  1. ShopCart.Instance.Clear()叫。
  2. ShopItemListView.ItemShource将是空的!不在 UI 上的项目!
  3. 但是TotalAmount's 的文本没有更改为 0.0!它仍然具有以前的值。

似乎在 UI 元素上 TotalAmount 没有刷新!在调试中,我在清除后看到ShopItemListView.ItemsSource列表为空。

所以ShopItem_ItemRemoved函数没有被调用!

这里是 Xaml.cs

public ShopView()
    {
        InitializeComponent();
        BindingContext = new ShopViewModel();

        ShopItemListView.ItemsSource = Shop.Instance.ShopItems;
        // This is triggered, it works
        ShopItemListView.ItemAppearing += ShopItem_NewItemAdded;
        // This event is not triggered, it does not work
        ShopItemListView.ItemDisappearing += ShopItem_ItemRemoved;
    }

    // This event is not triggered, it does not work
    private void ShopItem_ItemRemoved(object sender, ItemVisibilityEventArgs e)
    {
       // If I put a breakpoint here the debugger never comes into this method
        TotalAmount.Text = Shop.Instance.ShopItems.Sum(si => si.Price).ToString();
        if (Shop.Instance.ShopItems.Count == 0) {
            ShopInformation.IsVisible = false;
        }
    }

     // This is triggered, it works.
    private void ShopItem_NewItemAdded(object sender, ItemVisibilityEventArgs e)
    {
        TotalAmount.Text = Shop.Instance.ShopItems.Sum(si => si.Price).ToString();
        ShopInformation.IsVisible = true;
    }

这是购物车单例实例

public sealed class ShopCart : INotifyPropertyChanged
    {
        private static readonly ShopCart _instance = new ShopCart();

        private ShopCart()
        {
            ShopItems = new ObservableCollection<ShopCartItem>();
        }

        public static ShopCart Instance
        {
            get
            {
                return _instance;
            }
        }

        public ObservableCollection<ShopCartItem> ShopItems { get; set; }

        public void AddItem(ShopCartItem ShopCartItem)
        {
            ShopItems.Add(ShopCartItem);
            OnPropertyChanged("ShopItems");
        }

        public void Clear()
        {
            ShopItems.Clear();
            OnPropertyChanged("ShopItems");
        }

        #region INotifyPropertyChanged Implementation
        public event PropertyChangedEventHandler PropertyChanged;

        void OnPropertyChanged([CallerMemberName] string propertyName = "")
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
        #endregion
    }

ShopCart 实现了 INotifyPropertyChanged 接口。但似乎没有通知 UI 元素。

TotalAmount从购物车中删除所有商品后,如何刷新 UI 上的标签?

标签: xamarinxamarin.formsxamarin.iosxamarin.android

解决方案


也许您误用了ItemDisappearing。此方法仅用于虚拟化。从屏幕上删除列表时,不能保证所有可见项目都会触发。

这意味着如果您有一个包含 100 个项目的列表,但由于单元格的大小,您一次只能看到 10 个,因为一旦您向下滚动并且一个新单元格进入视图,并且顶部单元格滚动离开屏幕,ItemDisappearing 事件会开火。

如果您只想ShopItems在屏幕上显示 listView 的 ItemsSource(在您的情况下为 Count)计数。您可以使用绑定和转换器:

首先创建一个转换器:

public class ArrayToCountConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        ObservableCollection<ShopCartItem> collection = value as ObservableCollection<ShopCartItem>;

        return "There are" + collection.Count + "items";
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

然后像这样使用它:

<ContentPage.Resources>
    <ResourceDictionary>
        <local:ArrayToCountConverter x:Key="ArrayToCountConverter"/>
    </ResourceDictionary>
</ContentPage.Resources>

<Label Text="{Binding ShopItems, Converter={StaticResource ArrayToCountConverter}}"/>

您还需要设置BindingContext

public ShopCart shopCart = ShopCart.Instance;
public MainPage()
{
    InitializeComponent();

    this.BindingContext = shopCart;

    MyListView.ItemsSource = shopCart.ShopItems;
}

这样当你ShopItems在 ViewModel 中添加或清除时,标签会显示计数。


推荐阅读