我正在使用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();
}
}
答案 0 :(得分:1)
我建议listview缓存策略可能会解决此问题,默认值为ListView的RetainElement,因此请在ListView中使用 CachingStrategy =“ RecycleElement” 。
关于listview缓存策略,您可以看一下:
答案 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);
}