Xamarin 表单集合视图 ItemsSource 绑定未更新 UI

Posted

技术标签:

【中文标题】Xamarin 表单集合视图 ItemsSource 绑定未更新 UI【英文标题】:Xamarin Forms Collection view ItemsSource Binding not updating the UI 【发布时间】:2019-10-15 00:21:43 【问题描述】:

如果我在后面的代码中设置绑定,Xamarin.Forms 4.0 集合视图 ItemsSource 绑定无法按预期工作。这些项目基于源集合的初始值显示,但是当源集合更新时,UI 不会更新。如果我在 xaml 中设置绑定,则同样有效。

后面的代码:

    public MainPage()
    
        this.InitializeComponent();
        this.BindingContext = this.mainViewModel = new MainViewModel();


        CollectionView courseCollectionView = new CollectionView
        
            ItemSizingStrategy = ItemSizingStrategy.MeasureFirstItem,
            ItemTemplate = new DataTemplate(typeof(ItemView))
        ;


     courseCollectionView.SetBinding(CollectionView.ItemsSourceProperty, 
     new Binding()  Source = this.mainViewModel.CountryNames, Mode = 
     BindingMode.TwoWay );

     courseCollectionView.ItemsLayout = new GridItemsLayout(4, 
      ItemsLayoutOrientation.Vertical);

        this.CoursesStack.Children.Clear();
        this.CoursesStack.Children.Add(courseCollectionView);

    

查看用于 ItemsSource 绑定的模型属性:

   ObservableCollection<Country> countryNames;

    public ObservableCollection<Country> CountryNames
    
        get => this.countryNames;
        set
        
            this.countryNames = value;
            RaisePropertyChanged("CountryNames");
        
    

预期:应根据绑定到 ItemsSource 属性的 ObsevableCollection(从集合中添加/删除项目)所做的更改更新视图。

实际:视图不会随着 ObservableCollection 的更改而更新。

【问题讨论】:

当您说“未更新更改”时,您的意思是从集合中添加/删除项目吗?或者您的意思是更改集合中各个项目的属性? 当我从集合中添加/删除项目时,UI 没有更新。 您不需要在后面的代码中绑定ItemsSource - 您可以直接分配它。但这可能不是根本问题。你也不应该需要一个 CollectionView 的双向绑定 是的,我可以在 xaml 中绑定它,但是,这里提到的集合视图上有一个打开的错误/任务github.com/xamarin/Xamarin.Forms/issues/5354。而且我需要在设备方向更改时更新 ItemsLayout。无论如何@ottermatic 解决方案对我有用。谢谢你:) @Jason 更改项目属性时怎么样? 【参考方案1】:

关于在使用 CollectionView 时更新 UI,我做了一个示例,你可以看看:

public partial class MainPage : ContentPage

    public mainvidemodel viewmodel  get; set; 
    public MainPage()
    
        InitializeComponent();
        viewmodel = new mainvidemodel();
        this.BindingContext = viewmodel;

        CollectionView collectionView = new CollectionView();

        collectionView.SetBinding(ItemsView.ItemsSourceProperty, "countries");

        collectionView.ItemTemplate = new DataTemplate(() =>
        
            StackLayout stacklayout = new StackLayout();

            Label label1 = new Label();
            label1.SetBinding(Label.TextProperty,"Id");

            Label label2 = new Label();
            label2.SetBinding(Label.TextProperty, "Name");

            Label label3 = new Label();
            label3.SetBinding(Label.TextProperty, "caption");


            stacklayout.Children.Add(label1);
            stacklayout.Children.Add(label2);

            stacklayout.Children.Add(label3);
            return stacklayout;

        );
        Button btn = new Button()  Text = "btn", WidthRequest = 200, HeightRequest = 50 ;
        btn.Clicked += Btn_Clicked;
        stacklayout1.Children.Add(collectionView);
        stacklayout1.Children.Add(btn);

    

    private void Btn_Clicked(object sender, EventArgs e)
    
        viewmodel.countries.Add(new Country()   Id = 8, Name = "country8", caption = "caption 8" );
    

public class mainvidemodel

    public ObservableCollection<Country> countries  get; set; 
    public mainvidemodel()
    
        countries = new ObservableCollection<Country>()
        
            new Country()Id=1,Name="country1",caption="caption 1",
            new Country()Id=2,Name="country2",caption="caption 2",
            new Country()Id=3,Name="country3",caption="caption 3",
            new Country()Id=4,Name="country4",caption="caption 4",
            new Country()Id=5,Name="country5",caption="caption 5",
            new Country()Id=6,Name="country6",caption="caption 6",
            new Country()Id=7,Name="country7",caption="caption 7",

        ;

    

public class Country

    public int Id  get; set; 
    public string Name  get; set; 
    public string caption  get; set; 

【讨论】:

【参考方案2】:

我相信你的绑定是错误的。尝试: courseCollectionView.SetBinding(CollectionView.ItemsSourceProperty, nameof(mainViewModel.CountryNames));

您需要指定Path (mainViewModel.CountryNames) 而不是Source

【讨论】:

现在完美运行!非常感谢。是的,我的绑定错误。【参考方案3】:

在这种情况下,尝试从 INotifyPropertyChanged 扩展 MainPage,而不是设置属性中的 RaisePropertyChanged("CountryNames"),使用 OnPropertyChanged()

【讨论】:

MainViewModel 已经从 INotifyPropertyChanged 扩展而来,如果我在 Xaml 中设置了 ItemsSource 绑定,它的工作正常。

以上是关于Xamarin 表单集合视图 ItemsSource 绑定未更新 UI的主要内容,如果未能解决你的问题,请参考以下文章

集合视图。屏幕上的 const 图像数量。 Xamarin 表单

如何在 xamarin 表单的集合视图中的最后一项旁边添加图像/按钮?

如何在 Xamarin 表单中使用 MVVM 仅为集合视图中的选定框架设置颜色?

预选的 CollectionView 在 xamarin 表单中不起作用

在 Xamarin 表单中将 Observable 集合绑定到我的 ListView 时遇到问题

如何在 Xamarin 表单的另一个视图中重用缓存的图像