【问题标题】:Binding data to a Scrollview Stacklayout in Xamarin Forms将数据绑定到 Xamarin 表单中的 Scrollview Stacklayout
【发布时间】:2019-08-18 06:12:22
【问题描述】:

我看到一篇关于 xamarin 表单的文章,其中包含一些“可绑定的爱”https://blog.xamarin.com/xamarin-forms-3-5-a-little-bindable-love/。

我想尝试一下并创建一个滚动列表,但由于某种原因,我绑定的数据似乎没有出现在视图中。绑定应该可以正常工作,因为在我的 XAML 中我绑定了很多其他东西并且它可以成功运行,但是由于某种原因,这个特定的绑定不起作用。

XAML:

<ScrollView>
   <StackLayout BackgroundColor="Transparent" BindableLayout.ItemsSource="{Binding CategoriesList}"  >
                <BindableLayout.ItemTemplate>
                        <DataTemplate>         
                           <StackLayout Orientation = "Horizontal" HeightRequest="150" WidthRequest="80">

                                <Button Text="{Binding Name}" />

                         </StackLayout>
                       </DataTemplate>
                </BindableLayout.ItemTemplate>          
             </StackLayout>
        </ScrollView>

这是我的列表在 VM 中的外观:

private ObservableCollection<Categories> _Categories;
    public ObservableCollection<Categories> CategoriesList
    {
        get
        {
            return this._Categories;
        }
        set
        {
            if (_Categories != value)
            {
                this._Categories = value;
                RaisePropertyChanged("CategoriesList");
            }
        }
    }

当我为它创建数据时:

        CategoriesList = new ObservableCollection<Categories>();

        CategoriesList.Add(new Categories() { Name = "Data 1", ID = "1" });
        CategoriesList.Add(new Categories() { Name = "Data 2", ID = "2" });
        CategoriesList.Add(new Categories() { Name = "Data 3", ID = "3" });

【问题讨论】:

    标签: c# xamarin.forms binding


    【解决方案1】:

    我猜你的 getter 和 setter 有问题。一旦更改,它就不会正确更新值。我已经使用INotifyPropertyChanged 完成了,它工作正常。

    MainPage.xaml:

        <?xml version="1.0" encoding="utf-8"?>
    <ContentPage
        xmlns="http://xamarin.com/schemas/2014/forms"
        xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
        xmlns:local="clr-namespace:App"
        x:Class="App.MainPage">
        <ContentPage.Content>
            <ScrollView HorizontalOptions="FillAndExpand">
                <StackLayout
                    HorizontalOptions="FillAndExpand"
                    BackgroundColor="Transparent"
                    BindableLayout.ItemsSource="{Binding CategoriesList}">
                    <BindableLayout.ItemTemplate>
                        <DataTemplate>
                            <StackLayout
                                Orientation="Horizontal"
                                HeightRequest="150"
                                HorizontalOptions="FillAndExpand">
                                <Button
                                    Text="{Binding Name}" />
                            </StackLayout>
                        </DataTemplate>
                    </BindableLayout.ItemTemplate>
                </StackLayout>
            </ScrollView>
        </ContentPage.Content>
    </ContentPage>
    

    MainPage.xaml.cs:

      namespace App
      {
        public partial class MainPage : ContentPage
        {
    
            public MainPage()
            {
                InitializeComponent();
                BindingContext = new MainPageViewModel();
            }
    
        }
    }
    

    MainPageViewModel:

     public class MainPageViewModel : BaseViewModel
    {
        private ObservableCollection<CategoriesModel> _Categories;
        public ObservableCollection<CategoriesModel> CategoriesList
        {
            get
            {
                return this._Categories;
            }
            set
            {
                if (_Categories != value)
                {
                    this._Categories = value;
                    SetPropertyValue(ref _Categories, value);
    
                }
            }
        }
    
        public MainPageViewModel()
        {
    
            CategoriesList = new ObservableCollection<CategoriesModel>
            {
                new CategoriesModel() { Name = "Data 1", ID = "1" },
                new CategoriesModel() { Name = "Data 2", ID = "2" },
                new CategoriesModel() { Name = "Data 3", ID = "3" },
                new CategoriesModel() { Name = "Data 4", ID = "4" },
                new CategoriesModel() { Name = "Data 5", ID = "5" },
                new CategoriesModel() { Name = "Data 6", ID = "6" },
                new CategoriesModel() { Name = "Data 7", ID = "7" }
            };
        }
    }
    

    我的 BaseViewModel 扩展了 INotifyPropertyChanged:

    public class BaseViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
    
        protected void OnPropertyChanges([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    
        protected void SetPropertyValue<T>(ref T bakingFiled, T value, [CallerMemberName] string proertyName = null)
        {
            bakingFiled = value;
            OnPropertyChanges(proertyName);
    
        }
    
    }
    

    所有视图模型类都扩展了 BaseViewModel 以便访问SetPropertyValue() 方法。

    输出:

    【讨论】:

    • 那么我会用“BaseViewModel”替换我正在使用的视图模型上的 INotifyPropertyChanged 吗?我是否需要在该视图模型中添加更多内容?
    • 不,你不需要再添加了。只需替换为我的代码。检查我更新的代码。
    • 这太奇怪了。我复制了确切的代码,但我没有看到任何项目正在显示。你的 xaml 看起来如何?
    • 是否使用stacklayout绑定?
    • 是的,BaseViewModel 提供了类似代码可重用性的功能。这就是为什么我更喜欢继承来减少代码重复。
    猜你喜欢
    • 1970-01-01
    • 2017-12-30
    • 1970-01-01
    • 1970-01-01
    • 2016-08-13
    • 2020-03-21
    • 1970-01-01
    • 2021-10-02
    • 2016-06-26
    相关资源
    最近更新 更多