Xamarin.Forms 无法通过 ViewModel 将 ObservableCollection 绑定到 CollectionList

Posted

技术标签:

【中文标题】Xamarin.Forms 无法通过 ViewModel 将 ObservableCollection 绑定到 CollectionList【英文标题】:Xamarin.Forms unable to bind ObservableCollection to CollectionList via ViewModel 【发布时间】:2021-12-10 15:40:15 【问题描述】:

我遇到了这个问题,首先我初始化了我的 ShoppingViewModel(从另一个 ViewModel 中的命令)

使用我的 ShoppingViewModel - 我调用 GetProducts 方法创建产品集合,然后导航到 ShoppingView - 我尝试将这个集合绑定到集合视图。

失败的地方是将一个绑定到另一个。

如果我通过构造函数将集合传递给视图并手动将其附加到 CollectionView 的 ItemSource 属性,它工作正常;

我查阅了几篇关于此的文章,甚至通过了几门 Udemy 课程来解决这个问题,我会尝试将其更改为 listview(从集合视图并使用绑定上下文) - 似乎没有任何工作 - 我不是确定我哪里出错了;

我还尝试查看更改绑定上下文引用是否会有所帮助 - 请帮助我了解我哪里出了问题

购物视图的 XAML 如下

    <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"  
           xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"    
xmlns:vm="clr-namespace:FurniturePhoneApp.ViewModel"
         x:Class="FurniturePhoneApp.View.ShoppingView"
 >

<ContentPage.Resources>
    <ResourceDictionary>
        <vm:ShoppingViewModel  x:Key="vm" />
    </ResourceDictionary>
</ContentPage.Resources>

<ContentPage.Content BindingContext="StaticResource vm">
    <StackLayout>
        <Label Text="Below is the selection of our products"
            VerticalOptions="CenterAndExpand" 
            HorizontalOptions="CenterAndExpand" />


        <CollectionView  x:Name="CvProducts"
                            SelectionMode="Single"
                            SelectionChanged="CvProducts_SelectionChanged"
                        ItemsSource="Binding Products">
            <CollectionView.ItemsLayout>
                <GridItemsLayout Orientation="Vertical"
                                     Span="2"
                                     VerticalItemSpacing="20"
                                     HorizontalItemSpacing="0" />
            </CollectionView.ItemsLayout>
            <CollectionView.Header>
                <StackLayout>
                    <Label Margin="15,50,15,15"
                               Text="Explore"
                               FontAttributes="Bold"
                               FontSize="Title"
                               TextColor="#2C2C2C" />
                    <CollectionView  x:Name="CvCategories"
                                         HeightRequest="200"
                                         SelectionMode="Single"
                                         SelectionChanged="CvCategories_SelectionChanged">
                        <CollectionView.ItemsLayout>
                            <LinearItemsLayout Orientation="Horizontal" />
                        </CollectionView.ItemsLayout>
                        <CollectionView.ItemTemplate>
                            <DataTemplate>
                                <StackLayout Orientation="Horizontal">
                                    <Frame Padding="0"
                                               BackgroundColor="Transparent"
                                               Margin="15,0,15,0"
                                               HasShadow="True">
                                        <StackLayout Orientation="Vertical">
                                            <Frame Padding="0"
                                                       CornerRadius="15"
                                                       IsClippedToBounds="True"
                                                       HeightRequest="150"
                                                       WidthRequest="150"
                                                       HorizontalOptions="Center">
                                                <Image Aspect="AspectFit"
                                                           HorizontalOptions="FillAndExpand"
                                                           VerticalOptions="FillAndExpand"
                                                           Source="Binding FullImageUrl"/>
                                            </Frame>
                                            <Label TextColor="#2C2C2C"
                                                       HorizontalTextAlignment="Center"
                                                       FontSize="Medium"
                                                       Text="Binding Name"/>
                                        </StackLayout>
                                    </Frame>
                                </StackLayout>
                            </DataTemplate>
                        </CollectionView.ItemTemplate>
                    </CollectionView>

                    <Label Margin="15,15,15,0"
                               Text="Trending Products"
                               TextColor="#2C2C2C"
                               FontSize="Title"
                               FontAttributes="Bold" />
                </StackLayout>
            </CollectionView.Header>
            <CollectionView.ItemTemplate>
                <DataTemplate>
                    <StackLayout Spacing="0">
                        <Frame CornerRadius="10"
                                   HasShadow="False"
                                   Margin="15,0,15,0"
                                   Padding="20">
                            <StackLayout Spacing="5"
                                             Orientation="Vertical">
                                <Image Aspect="Fill"
                                           HeightRequest="120"
                                           Source="Binding FullImageUrl"/>
                                <Label TextColor="#2C2C2C"
                                           Text="Binding Name"/>
                                <Label TextColor="#FA6400"
                                           Text="Binding Price, StringFormat='$0'"/>
                            </StackLayout>
                        </Frame>
                    </StackLayout>
                </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>
    </StackLayout>

</ContentPage.Content>

我的 ShoppingViewModel 在下面

namespace FurniturePhoneApp.ViewModel

    public class ShoppingViewModel : INotifyPropertyChanged
    
        public ObservableCollection<ProductByCategory> Products;

        public ShoppingViewModel()
        
            GetProducts();
        

        public async void GetProducts()
        
            var items = await ApiService.GetProductByCategory(2);

            ObservableCollection<ProductByCategory> Products = new ObservableCollection<ProductByCategory>();
            foreach (var item in items)
            
                Products.Add(item);
            

            if (Products != null)
            
                // await Application.Current.MainPage.Navigation.PushAsync(new ShoppingView());
                await Application.Current.MainPage.Navigation.PushAsync(new ShoppingView(Products));
            

        

        public event PropertyChangedEventHandler PropertyChanged;

        private void OnPropertyChanged(string propertyName)
        
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        
    

【问题讨论】:

【参考方案1】:

您正在GetProducts 方法中创建一个新的局部变量。您只需评论该行并创建 ObservableCollection 来声明您的变量

    public ObservableCollection<ProductByCategory> Products = new ObservableCollection<ProductByCategory>();

    public ShoppingViewModel()
    
        GetProducts();
    

    public async void GetProducts()
    
        var items = await ApiService.GetProductByCategory(2);

        //ObservableCollection<ProductByCategory> Products = new ObservableCollection<ProductByCategory>();
        foreach (var item in items)
        
            Products.Add(item);
        

        if (Products != null)
        
            // await Application.Current.MainPage.Navigation.PushAsync(new ShoppingView());
            await Application.Current.MainPage.Navigation.PushAsync(new ShoppingView(Products));
        

    

您尝试了很多设置绑定上下文的地方,我通常会这样做(我的个人喜好)

    在 XAML 中(没有你所做的资源)

    <ContentPage.BindingContext>
     <vm:IsNullOrEmptyConverterViewModel />
    </ContantPage.BindingContext
    

    或者在页面构造器中

    public myNewPage()
    
    BindingContext = new ViewModel();
    InitializeComponent();
    
    

【讨论】:

以上是关于Xamarin.Forms 无法通过 ViewModel 将 ObservableCollection 绑定到 CollectionList的主要内容,如果未能解决你的问题,请参考以下文章

Catel 与 Xamarin.Forms

包“apppxbundle”需要很长时间来处理。无法将更新推送到 Windows 商店 [UWP] [Xamarin.Forms]

无法在 Xamarin.Forms 中实现导航

无法使用 PCLStorage 或 Xamarin Forms Labs 在 Android 文件系统中创建文件夹/文件

无法反序列化当前 JSON 对象 xamarin.forms

Xamarin.Forms 监听Button的按下释放事件