首页 > 解决方案 > Listview 没有正确刷新项目视图

问题描述

我正在开发一个带有 xamarin 表单和 MVVM 模式的应用程序。我有一个包含三个按钮的列表视图页面,但始终只有 2 个可见按钮,并且当我按下按钮时会更改其中两个按钮的可见性。问题是,对于前十个项目,它按预期工作,按下按钮并消失并出现另一个,但是在第 10 个项目之后,当我按下按钮时它消失但另一个直到我滚动列表才出现查看项目在屏幕外的位置。当项目离开屏幕并重新出现在屏幕上时,按钮会出现。按钮的可见性被控制更改绑定到按钮的 IsVisible 属性的布尔属性,其中一个带有转换器以否定属性的值。这是一个存储库您可以克隆并查看代码并进行测试,这可能与我的 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;
        }
    }

基本视图模型

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();
        }
    }

标签: c#androidlistviewxamarin.formsxamarin.android

解决方案


我建议 listview Caching Strategy 可能会解决这个问题,ListView 的默认值为 RetainElement,因此在 ListView 中使用CachingStrategy="RecycleElement"

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

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


推荐阅读