简体   繁体   English

在 Xamarin Forms 中将 x:DataType 设置为 ViewModel 时,CollectionView 项目不会更新

[英]CollectionView items does not update while setting x:DataType to ViewModel in Xamarin Forms

I have a CollectionView that has its ItemsSource bound to an ObservableCollection and it works fine.我有一个CollectionView ,它的ItemsSource绑定到ObservableCollection ,它工作正常。 But when I add x:DataType="viewmodels:MyPageViewModel" in the XAML, it does not show any items, even those items that are initialized in the ViewModel's constructor are not shown in the CollectionView .但是当我在 XAML 中添加x:DataType="viewmodels:MyPageViewModel"时,它没有显示任何项目,即使在 ViewModel 的构造函数中初始化的那些项目也没有显示在CollectionView中。 It also does not show updated items.它也不显示更新的项目。

Here's my XAML Code (MyPage.xaml):这是我的 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>

Here I have specified Binding in the C# Code Behind (MyPage.xaml.cs):这里我在后面的C#代码中指定了Binding(MyPage.xaml.cs):

BindingContext = new ViewModels.MyPageViewModel();

Here's my ViewModel (MyPageViewModel.cs):这是我的 ViewModel (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));
    }
}

Note that if I remove x:DataType="viewmodels:MyPageViewModel" , everything works fine.请注意,如果我删除x:DataType="viewmodels:MyPageViewModel" ,一切正常。 Also if I edit something in ColllectionView while the app is running, it renders the items properly as expected through XAML Hot Reload .此外,如果我在应用程序运行时在ColllectionView中编辑某些内容,它会通过XAML Hot Reload按预期正确呈现项目。 But it doesn't fulfil the need as it does not work if I rerun the Project again.但它不能满足需要,因为如果我再次重新运行项目,它就不起作用。

Is there a bug in Xamarin Forms, I am running the latest Xamarin.Forms 5.0.0.2515, I have also tried it in Xamarin.Forms 5.0.0.2478? Is there a bug in Xamarin Forms, I am running the latest Xamarin.Forms 5.0.0.2515, I have also tried it in Xamarin.Forms 5.0.0.2478? Or am I missing something?还是我错过了什么? any help would be much appreciated.任何帮助将非常感激。

Specify x:DataType="modelOfYourCollection" in <DataTemplate> of the CollectionView .CollectionView<DataTemplate>中指定x:DataType="modelOfYourCollection"

If you are using any control that has a DataTemplate you must also setup the compiled binding on it.如果您正在使用任何具有 DataTemplate 的控件,则还必须在其上设置已编译的绑定。 Here, we have a CollectionView that is data bound to an ObservableCollection<string> .在这里,我们有一个CollectionView ,它是数据绑定到ObservableCollection<string>的。 We can bring in the System namespace just like we did for the viewmodels:MyPageViewModel because we are using collection of string type and String class resides in System namespace.我们可以像对viewmodels:MyPageViewModel那样引入System命名空间,因为我们使用字符串类型的集合,并且 String class 驻留在 System 命名空间中。

  • Firstly, add namespace in root of the page:首先,在页面的根目录中添加命名空间:
xmlns:sys="clr-namespace:System;assembly=System.Runtime"
  • And then in your DataTemplate add:然后在您的DataTemplate中添加:
<DataTemplate x:DataType="sys:String">

If we are using our own Custom Model, add model's namespace at the root of the page and then specify model class in DataTemplate of the CollectionView .如果我们使用自己的自定义 Model,请在页面的根目录添加模型的命名空间,然后在CollectionViewDataTemplate中指定 model class。 Note that we have to use Model and not ViewModel in the DataTemplate .请注意,我们必须在DataTemplate中使用 Model 而不是 ViewModel 。

Rest of the code is correct Rest的代码是正确的

Final XAML Code will look like:最终 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>

Why use Compiled Bindings: Compiled bindings are resolved more quickly than classic bindings.为什么使用编译绑定:编译绑定比经典绑定解决得更快。 Hence, improves data binding performance in Xamarin.Forms applications.因此,提高了 Xamarin.Forms 应用程序中的数据绑定性能。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM