Как получить представление списка форм Xamarin для сброса пользовательской ячейки представления после удаления на Android?

Я реализую функцию прокрутки для удаления, используя пользовательскую ячейку представления и средство визуализации. У меня есть представление списка так:

https://i.stack.imgur.com/AzBQk.png

и при смахивании открывается кнопка, как показано ниже

https://i.stack.imgur.com/S87uj.png

Однако после нажатия кнопки удаления (которая успешно удаляет элемент из списка) ячейка просмотра, которая переместилась в позицию ячейки удаления, по-прежнему имеет открытую кнопку удаления:

https://i.stack.imgur.com/aMwux.png

Кто-нибудь знает, как предотвратить это? Мой пользовательский рендерер просто отображает события OnFling() и OnScroll().

Я также пробовал аналогичную вещь, используя Xamarin Forms Pan Gesture Recogniser, и столкнулся с той же проблемой.

EDIT 1: добавлены фрагменты кода

Пользовательский вид ячейки xaml

<ViewCell xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="SwipeViewCell" xmlns:local="CustomControls">
<Grid x:Name="SwipeViewCellGrid">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="70*"/>
        <ColumnDefinition Width="30*"/>
    </Grid.ColumnDefinitions>
    <StackLayout x:Name="HiddenContainer" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" Grid.Column="1"/>
    <local:GestureStackLayout x:Name="SwipeContainer" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" Grid.ColumnSpan="2" Grid.Column="0"/>
</Grid>

Custom View Cell .cs:

public partial class SwipeViewCell : ViewCell
{       

    private View _swipeContent;
    private View _hiddenContent; 


    public SwipeViewCell()
    {
        InitializeComponent();

        SwipeContainer.SwipeLeft += SwipeContainer_SwipeLeft;
        SwipeContainer.SwipeRight += SwipeContainer_SwipeRight; 
    }

    public View SwipeContent
    {
        get
        {
            return _swipeContent;
        }
        set
        {
            _swipeContent = value;
            SwipeContainer.Children.Add(SwipeContent);
            OnPropertyChanged();
        }
    }

    public View HiddenContent
    {
        get
        {
            return _hiddenContent;
        }
        set
        {
            _hiddenContent = value;
            HiddenContainer.Children.Add(HiddenContent);
            OnPropertyChanged();
        }
    }

    private void SwipeContainer_SwipeRight(object sender, EventArgs e)
    {
        SwipeContainer.TranslateTo(SwipeContainer.X, 0, 250, Easing.Linear);
    }

    private void SwipeContainer_SwipeLeft(object sender, EventArgs e)
    {
        SwipeContainer.TranslateTo(SwipeContainer.X - HiddenContainer.Width, 0, 250, Easing.Linear);
    }

}

Просмотр модели:

public class ViewModel
{

    private ObservableCollection<string> _data;     

    public ViewModel()
    {
         Data = new ObservableCollection<string>();
         Data.Add("a");
         Data.Add("c");
         Data.Add("b");
    }

    public ObservableCollection<string> Data
    {
        get { return _data; }
        set
        {
            _data= value;
            OnPropertyChanged();
        }
    }

     public ICommand Delete
    {
        get
        {
            return new Command((e) =>
            {
                _data.Remove(e as string);                    
                Data = _data
            });
        }
    }

}

XAML:

 <ListView ItemsSource="{Binding Data}" x:Name="Model" HorizontalOptions="FillAndExpand" IsVisible="True" VerticalOptions="FillAndExpand" SeparatorVisibility="Default" SeparatorColor="Black">
                <CustomControls:MultiListView.ItemTemplate>
                    <DataTemplate>                       
                            <CustomControls:SwipeViewCell  x:Name="Item">
                                <CustomControls:SwipeViewCell.SwipeContent>
                                    <StackLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" BackgroundColor="White">
                                        <Label Text="{Binding }"/>
                                    </StackLayout>
                                </CustomControls:SwipeViewCell.SwipeContent>
                                <CustomControls:SwipeViewCell.HiddenContent>
                                    <Button Text="Delete" Command="{Binding Delete}"  BindingContext="{Binding Source={x:Reference Model}, Path=BindingContext}" CommandParameter="{Binding Source={x:Reference Item}, Path=BindingContext}"  BackgroundColor="Red"></Button>
                                </CustomControls:SwipeViewCell.HiddenContent>
                            </CustomControls:SwipeViewCell>                          
                    </DataTemplate>
                <ListView.ItemTemplate>
            <ListView>

comment
не могли бы вы добавить свой код? я могу дать вам хорошее решение   -  person Mike Darwish    schedule 02.03.2017
comment
@MikeDarwish Я добавил несколько фрагментов   -  person DParry    schedule 02.03.2017
comment
Привет @DParry. У меня аналогичная проблема со старыми ячейками, сохраняющимися в моем пользовательском интерфейсе. Вы нашли решение этой проблемы?   -  person Chucky    schedule 01.04.2019
comment
@ Чаки Нет. Если я правильно помню, это связано с тем, как Xamarin.Android кэширует представления и повторно использует элементы в списке. Одна вещь, которую вы можете сделать (в зависимости от размера вашего списка и производительности), — это реализовать еще один настраиваемый элемент управления, который эмулирует представление списка, отображая набор макетов стека. Это, очевидно, будет менее производительным, однако вам не придется беспокоиться о кешированных представлениях. Если вам нужен пример того, как это сделать, дайте мне знать :)   -  person DParry    schedule 03.04.2019


Ответы (1)


В следующем полном примере, как вы можете это сделать, он отлично работает для меня:

1- Добавить класс, содержащий число, отображаемое в вашем списке

 public class NumberClass
    {
        public string Number{ get; set; }
    }

2-попробуйте использовать ObservableCollection для NumberClass следующим образом:

public class NumberClassList : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        public System.Collections.ObjectModel.ObservableCollection<NumberClass> _items;
        public ObservableCollection<NumberClass> Items
        {
            get { return _items; }
            set { _items = value; OnPropertyChanged("Items"); }
        }
        protected virtual void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged == null)
                return;
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        public SerialClassList(List<NumberClass> itemList)
        {
            Items = new ObservableCollection<NumberClass>();
            foreach (NumberClassitm in itemList)
            {
                Items.Add(itm);
            }
        }
    }

3-поместите свой список номеров на List<NumberClass>

    public List<NumberClass> allItems;

4-Используйте NumberClassList следующим образом:

 NumberClassList items;
    items = new NumberClassList(allItems);

5-установите пункт Источник для вашего ListView следующим образом:

ItemsSource = items.Items;

6-Создайте DataTemplate для ListView следующим образом: Примечания: кнопка "Удалить" и номер имеют одинаковую привязку

DataTemplate dt = new DataTemplate(() =>
            {
                var Number = new Label
                {
                    TextColor=Color.Black,
                    FontAttributes=FontAttributes.Bold,
                    HorizontalOptions = LayoutOptions.StartAndExpand
                };
               Number.SetBinding(Label.TextProperty, new Binding("Number"));
                var Deletebutton = new Button { Text = "Delete", HorizontalOptions = LayoutOptions.StartAndExpand  };
                Deletebutton.SetBinding(Button.CommandParameterProperty, new Binding("Number"));
                Deletebutton.Clicked += DeleteSerial;
                return new ViewCell
                {
                    View = new StackLayout
                    {
                        Orientation = StackOrientation.Horizontal,
                        VerticalOptions = LayoutOptions.FillAndExpand,                          
                        Children =
                        {
                            Number,
                            Deletebutton
                        }
                    }
                };
            });
 YourListView.ItemTemplate = dt;

7 — это реализация кнопки «Удалить»:

 public void DeleteSerial(object sender,EventArgs e)
            {
                var item = (Xamarin.Forms.Button)sender;
                SerialClass listitem = (from itm in items.Items
                                        where itm.Number == item.CommandParameter.ToString()
                             select itm)
                            .FirstOrDefault<SerialClass>();
            items.Items.Remove(listitem);             
        }
person Mike Darwish    schedule 02.03.2017
comment
Я могу удалить все в порядке, проблема в том, что элемент, который заменяет удаленную строку, автоматически выставляет область «удаления». - person DParry; 02.03.2017