У меня есть простое приложение, которое отображает контент из ObservableCollection of Labels в зависимости от того, какая кнопка в ObservableCollection кнопок нажата.Нажатием кнопки «Обновить» я хочу заменить метки и кнопки и отображать их.Для этого у меня есть привязки к соответствующим ObservableCollections, и я делаю .Clear () для каждой из коллекций перед обновлением.ObservableCollections корректно обновляется, но элементы, отображаемые на экране, являются как старыми, так и новыми элементами.Кажется, что мой макет не обновляется сам, скорее добавьте новый макет рядом с обновленными элементами.Следующие снимки экрана иллюстрируют проблему:
при нагрузке:
при обновлении:
Как остановить отображение старых элементов (первые кнопки 1 и 2, начальный элемент 1)?
MainPage.xaml:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage
x:Class="TestApp.MainPage"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:TestApp">
<StackLayout>
<Button Command="{Binding LoadCommand}" Text="Load" />
<Button Command="{Binding RefreshCommand}" Text="Refresh" />
<local:BindableStackLayout
HorizontalOptions="FillAndExpand"
Items="{Binding ButtonCollection}"
Orientation="Horizontal"
VerticalOptions="Start" />
<local:BindableStackLayout
HorizontalOptions="FillAndExpand"
Items="{Binding ItemCollection}"
VerticalOptions="FillAndExpand" />
</StackLayout>
</ContentPage>
MainPage.xaml.cs:
using Xamarin.Forms;
namespace TestApp
{
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
this.BindingContext = new MyViewModel();
}
}
}
MyViewModel.cs:
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using Xamarin.Forms;
namespace TestApp
{
class MyViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public ObservableCollection<View> ButtonCollection { get; set; }
public ObservableCollection<View> ItemCollection { get; set; }
public Command LoadCommand { get; set; }
public Command RefreshCommand { get; set; }
public List<string> ItemList { get; set; }
public int SelectedItem { get; set; }
public MyViewModel()
{
ButtonCollection = new ObservableCollection<View>();
ItemCollection = new ObservableCollection<View>();
LoadCommand = new Command(Load);
RefreshCommand = new Command(Refresh);
}
public void SelectItem(int item)
{
SelectedItem = item;
for (int i = 0; i < ItemList.Count; i++)
{
if (item == i)
{
ItemCollection[i].IsVisible = true;
ButtonCollection[i].BackgroundColor = Color.Yellow;
}
else
{
ItemCollection[i].IsVisible = false;
ButtonCollection[i].BackgroundColor = Color.LightGray;
}
}
}
public void Load()
{
ItemList = new List<string> { "Initial item 1", "Initial item 2" };
for (int i = 0; i < ItemList.Count; i++)
{
int copy = i;
ButtonCollection.Add(new Button { Command = new Command(() => { SelectItem(copy); }), FontSize = 32, Text = (i + 1).ToString(), HeightRequest = 100, HorizontalOptions = LayoutOptions.FillAndExpand });
ItemCollection.Add(new Label { Text = ItemList[i] });
}
SelectItem(0);
}
public void Refresh()
{
ItemList = new List<string> { "Updated item 1", "Updated item 2", "Updated item 3" };
ItemCollection.Clear();
ButtonCollection.Clear();
for (int i = 0; i < ItemList.Count; i++)
{
int copy = i;
ButtonCollection.Add(new Button { Command = new Command(() => { SelectItem(copy); }), FontSize = 32, Text = (i + 1).ToString(), HeightRequest = 100, HorizontalOptions = LayoutOptions.FillAndExpand });
ItemCollection.Add(new Label { Text = ItemList[i] });
}
System.Diagnostics.Debug.WriteLine(ItemCollection.Count);
SelectItem(0);
}
protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}
BindableStackLayout.cs
using Xamarin.Forms;
using System.Collections.Specialized;
using System.Collections.ObjectModel;
namespace TestApp
{
class BindableStackLayout : StackLayout
{
public static readonly BindableProperty ItemsProperty =
BindableProperty.Create(nameof(Items), typeof(ObservableCollection<View>), typeof(BindableStackLayout), null,
propertyChanged: (b, o, n) =>
{
(n as ObservableCollection<View>).CollectionChanged += (coll, arg) =>
{
switch (arg.Action)
{
case NotifyCollectionChangedAction.Add:
foreach (var v in arg.NewItems)
(b as BindableStackLayout).Children.Add((View)v);
break;
case NotifyCollectionChangedAction.Remove:
foreach (var v in arg.NewItems)
(b as BindableStackLayout).Children.Remove((View)v);
break;
}
};
});
public ObservableCollection<View> Items
{
get { return (ObservableCollection<View>)GetValue(ItemsProperty); }
set { SetValue(ItemsProperty, value); }
}
}
}