XAML 在Xamarin表单中将x:DataType设置为ViewModel时,CollectionView项不更新

2nbm6dog  于 2022-12-07  发布在  其他
关注(0)|答案(1)|浏览(200)

我有一个CollectionView,它的ItemsSource绑定到ObservableCollection,它工作得很好。但是当我在XAML中添加x:DataType="viewmodels:MyPageViewModel"时,它不显示任何项,甚至那些在ViewModel的构造函数中初始化的项也不显示在CollectionView中。它也不显示更新的项。

以下是我的XAML代码(MyPage.xaml):

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage ...
             xmlns:viewmodels="clr-namespace:MyProject.ViewModels"
             x:DataType="viewmodels:MyPageViewModel"
             x:Class="MyProject.Views.MyPage">

    <ContentPage.Content>
        <StackLayout>
            <CollectionView ItemsSource="{Binding Strings}">
                <CollectionView.ItemTemplate>
                    <DataTemplate>
                        <StackLayout>
                            <Label Text="{Binding .}" />
                        </StackLayout>
                    </DataTemplate>
                </CollectionView.ItemTemplate>
            </CollectionView>

            <Button Text="Add More" Command="{Binding AddMoreItemsCommand}" />
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

这里我在C#代码隐藏(MyPage.xaml.cs)中指定了绑定:

BindingContext = new ViewModels.MyPageViewModel();

以下是我的视图模型(MyPageViewModel.cs):

public class MyPageViewModel : INotifyPropertyChanged
{
    public ObservableCollection<string> Strings { get { return strings; } set { strings = value; OnPropertyChanged(nameof(Strings)); } }
    ObservableCollection<string> strings;

    public MyPageViewModel()
    {
        Strings = new ObservableCollection<string> { "1", "2", "3" };
    }

    public ICommand AddMoreItemsCommand => new Command(() =>
    {
        Strings.Add("4");
        Strings.Add("5");
        Strings.Add("6");
    });

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

请注意,如果我删除x:DataType="viewmodels:MyPageViewModel",一切都正常。此外,如果我在ColllectionView中编辑的东西,而应用程序正在运行,它渲染的项目正确,如预期通过XAML热重新加载。但它不满足需要,因为它不工作,如果我再次重新运行项目。
Xamarin表单有问题吗?我正在运行最新的Xamarin。表单5.0.0.2515,我也在Xamarin中试过。表单5.0.0.2478?或者我遗漏了什么?任何帮助都将不胜感激。

ep6jt1vc

ep6jt1vc1#

CollectionView<DataTemplate>中指定x:DataType="modelOfYourCollection"
如果您正在使用任何具有DataTemplate的控件,则还必须在其上设置已编译绑定。在这里,我们有一个CollectionView,它是数据绑定到ObservableCollection<string>的。我们可以引入System命名空间,就像我们对viewmodels:MyPageViewModel所做的那样,因为我们正在使用字符串类型的集合,而String类驻留在System命名空间中。

  • 首先,在页面的根目录下添加命名空间:
xmlns:sys="clr-namespace:System;assembly=System.Runtime"
  • 然后在DataTemplate中添加:
<DataTemplate x:DataType="sys:String">

如果我们使用自己的自定义模型,请在页面的根位置添加模型的命名空间,然后在CollectionViewDataTemplate中指定模型类。请注意,我们必须在DataTemplate中使用Model而不是ViewModel。
其余代码正确

最终的XAML程式码看起来会像:

<ContentPage ...
             xmlns:viewmodels="clr-namespace:MyProject.ViewModels"
             xmlns:models="clr-namespace:MyProject.Models"
             xmlns:sys="clr-namespace:System;assembly=System.Runtime"
             x:DataType="viewmodels:MyPageViewModel"
             x:Class="MyProject.Views.MyPage">
    ...

    <CollectionView ItemsSource="{Binding Strings}">
        <CollectionView.ItemTemplate>
            <DataTemplate x:DataType="sys:String">
                <Label Text="{Binding .}" />
            </DataTemplate>
        </CollectionView.ItemTemplate>
    </CollectionView>

    <!-- For collection of your custom model -->

    <CollectionView ItemsSource="{Binding Monkeys}" >
        <CollectionView.ItemTemplate>
            <DataTemplate x:DataType="models:MonkeyModel">
                <Label Text="{Binding MonkeyName}" />
            </DataTemplate>
        </CollectionView.ItemTemplate>
    </CollectionView>
</ContentPage>

**为什么使用编译绑定?**编译绑定的解析速度比传统绑定快。因此,可以提高Xamarin.Forms应用程序中的数据绑定性能。

相关问题