Listview无法正确刷新项目视图

时间:2019-06-26 18:29:40

标签: c# android listview xamarin.forms xamarin.android

我正在使用xamarin表单和MVVM模式开发应用程序。我有一个带有列表视图的页面,该页面具有三个按钮,但是始终只有2个可见物,当我按下一个按钮时,会更改其中两个的可见性。问题在于,对于前十个项目,其工作原理与预期的一样,请按按钮并消失并显示另一个项目,但是当我按按钮时,在第10个项目之后会消失,但直到我选择列表时其他项目才出现查看到项目不在屏幕上的位置。当项目不在屏幕上并返回到屏幕上时,按钮出现。控制按钮的可见性可以更改一个布尔属性,该布尔属性绑定到按钮的IsVisible属性,并且其中一个通过转换器与否定该属性的值绑定。这是一个repository,您可以克隆并查看代码并进行测试,也许与我的Visual Studio有关。

最初,我认为这可能是出于竞争条件,并且使更改变量的方法是同步的,但它不起作用。

这是我的列表视图

   <ListView ItemsSource="{Binding Items}"
                          HasUnevenRows="True"
                          SeparatorVisibility="None"
                          IsRefreshing="False">
                    <ListView.ItemTemplate>
                        <DataTemplate>
                            <ViewCell>
                                <StackLayout>
                                    <Label Text="{Binding Name}"/>
                                    <StackLayout Orientation="Horizontal">
                                        <Button Text="One" 
                                                HorizontalOptions="CenterAndExpand"
                                                TextColor="Green"                                                     
                                                BackgroundColor="White"
                                                BorderColor="Green"
                                                BorderWidth="1"
                                                WidthRequest="150" />
                                        <Button Text="Two"
                                                HorizontalOptions="CenterAndExpand"
                                                BackgroundColor="Green"
                                                TextColor="White"
                                                Command="{Binding TestCommand}"
                                                WidthRequest="150"
                                                IsVisible="{Binding TestVariable, Converter={StaticResource negate}}" />
                                        <Button Text="Three"
                                                HorizontalOptions="CenterAndExpand"
                                                BackgroundColor="Red"
                                                Command="{Binding TestCommand}"
                                                TextColor="White"
                                                WidthRequest="150"
                                                IsVisible="{Binding TestVariable}" />
                                    </StackLayout>
                                </StackLayout>
                            </ViewCell>
                        </DataTemplate>
                    </ListView.ItemTemplate>
                </ListView>

视图模型

 public class ListViewTestModel : BaseViewModel
    {
        private List<ListItemTestModel> items;
        public List<ListItemTestModel> Items
        {
            get => items;
            set
            {
                SetValue(ref items, value);
            }
        }


        public ListViewTestModel()
        {
            List<ListItemTestModel> itemList = new List<ListItemTestModel>();

            for (int i = 0; i < 40; i++)
            {
                itemList.Add(new ListItemTestModel { Name = "Test" });
            }

            Items = itemList;
        }
    }

另一个绑定到listView中每个项目的视图模型


public class ListItemTestModel : BaseViewModel
    {
        private bool testVariable;
        public string Name { get; set; }

        public bool TestVariable
        {
            get
            {
                return testVariable;
            }
            set
            {
                SetValue(ref testVariable, value);
            }
        }

        public Command TestCommand { get; set; }

        public ListItemTestModel()
        {
            TestCommand = new Command(() =>
            {
                TestMethod();
            });
        }

        public void TestMethod()
        {
            TestVariable = !TestVariable;
        }
    }

BaseViewModel

public class BaseViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

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

        protected void SetValue<T>(ref T backingField, T value, [CallerMemberName] string propertyName = null)
        {
            if (EqualityComparer<T>.Default.Equals(backingField, value))
            {
                return;
            }

            backingField = value;
            OnPropertyChanged(propertyName);
        }
    }

以及页面后面的代码

  public partial class MainPage : ContentPage
    {
        public ListViewTestModel ViewModel { get; }
        public MainPage()
        {
            ViewModel = new ListViewTestModel();
            BindingContext = ViewModel;
             InitializeComponent();
        }
    }

2 个答案:

答案 0 :(得分:1)

我建议listview缓存策略可能会解决此问题,默认值为ListView的RetainElement,因此请在ListView中使用 CachingStrategy =“ RecycleElement”

关于listview缓存策略,您可以看一下:

https://docs.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/listview/performance#caching-strategy

答案 1 :(得分:1)

您绝对应该为商品输入ObservableCollection类型,这样您就可以观察和显示所有更改

   private ObservableCollection<ListItemTestModel> items;
        public ObservableCollection<ListItemTestModel> Items
        {
            get => items;
            set => SetValue(ref items, value);

        } 

并且您应该将BindingContext设置为 AFTER 后,初始化视图之前,将传播已更改的InitializeComponent()方法或属性。

public MainPage()
    {      
        InitializeComponent();
        BindingContext = new ListViewTestModel();;
    }



public ListViewTestModel()
        {
            List<ListItemTestModel> itemList = new List<ListItemTestModel>();

            for (int i = 0; i < 40; i++)
            {
                itemList.Add(new ListItemTestModel { Name = "Test" });
            }

            Items = new ObservableCollection<ListItemTestModel>(itemList);
        }