【问题标题】:New Xamarin.Forms CollectionView doesn't allow multi pre-selection新的 Xamarin.Forms CollectionView 不允许多预选
【发布时间】:2019-09-05 17:22:49
【问题描述】:

我的 Xamarin.Forms 项目中有一个 CollectionView:

<CollectionView ItemsSource="{Binding Categories}" ItemSizingStrategy="MeasureFirstItem" x:Name="CategoryColView"
                SelectionMode="Multiple" SelectionChangedCommand="{Binding SelectionChangedCommand}" 
                SelectionChangedCommandParameter="{Binding Source={x:Reference CategoryColView}, Path=SelectedItems}"
                SelectedItems="{Binding SelectedCategoryItems}">
   <CollectionView.ItemTemplate>
      <DataTemplate>
         <StackLayout ...>
            <BoxView .../>
               <StackLayout ...>
                  <Label .../>
                     <Image .../>
               </StackLayout>
            <BoxView/>
         </StackLayout>
      </DataTemplate>
   </CollectionView.ItemTemplate>
</CollectionView>

我包含了整个 XAML 元素,但唯一重要的部分是 SelectedItems 属性。它绑定到以下视图模型实现:

class ViewModel {

    private ObservableCollection<object> selectedCategories { get; set; }
    public ObservableCollection<object> SelectedCategories {
        get => selectedCategories;
        set {
            selectedCategories = value;
            OnPropertyChanged();
        }

    //...

    ctor() {
        //...
        var alreadySelectedCategoryItems = alreadySelectedCategories.Select(pc => new CategoryItem { PlantCategory = pc, IsSelected = true }).Cast<object>();
        SelectedCategoryItems = new ObservableCollection<object>(alreadySelectedCategoryItems);
        //...
    }
}

其余的实现应该是无关紧要的。我的目标是预先选择值。

首先:我注意到如果ObservableCollection&lt;T&gt; 中的T 不是object,则所有内容都会被忽略。就像微软的例子here一样。如果T 是例如CategoryItem 类型的,实际上什么都没有发生,好像 ObserveableCollection 被完全忽略了。

第二个: alreadySelectedCategoryItem 在调试器模式下包含 2 个元素,但随后构造函数中的最后一行抛出一个:

System.ArgumentOutOfRangeException

索引超出范围。必须为非负数且小于集合的大小。

参数名称:索引

当然,因为这是 Xamarin.Forms 和 VS for Mac,所以错误是在 Main 函数上抛出的,而不是在它的实际位置......

是我做错了什么,还是 CollectionView 仍然有问题?

【问题讨论】:

  • 嗯不确定您的第一个假设,即 T 应该是 Object。看看我用 CollectionView 做的一个测试应用程序,我能够将 ObservableCollection 与常规类一起使用。 github.com/Depechie/CollectionViewChallenge/blob/master/…github.com/Depechie/CollectionViewChallenge/blob/master/…
  • 第二个假设将是一个真正的 Xamarin 错误,我可以在上面链接的示例应用程序中重现它。我会提交报告。
  • @Depechie 感谢您的第一次澄清!那么它一定是我的代码中的东西。
  • 是的,如果第二个确实是一般错误,github issue 将是记录它的最佳位置:)

标签: c# xamarin xamarin.forms


【解决方案1】:

问题是我正在创建新的 CategoryItem 实例作为预选实例,这是无效的,因为默认情况下它们与 CollectionView.ItemsSource 属性中的实例不同。我应该过滤 ItemsSource 实例并将它们作为预选实例。像这样:

var alreadySelectedCategoryItems = alreadySelectedCategories.Select(pc => new CategoryItem { PlantCategory = pc, IsSelected = true }).Cast<object>();
SelectedCategoryItems = Categories
    .Where(sci => 
         alreadySelectedCategoryItems.Any(alreadySelected => 
              alreadySelected.PlantCategory.Id == sci.PlantCategory.Id);

因此项目是从 ItemsSource 本身中选择出来的,而不是作为新项目创建的。

虽然错误信息不是我们想要的,所以Xamarin.Forms team is going to fix that

【讨论】:

    【解决方案2】:

    SelectedItems 是只读的,你不能在 xaml 中像 SelectedItems="{Binding SelectedCategoryItems}" 这样使用

    您可以尝试更改您的后台代码,例如:

    CategoryColView.SelectedItems.Add(your selectItem 1);
    CategoryColView.SelectedItems.Add(your selectItem 2);
    CategoryColView.SelectedItems.Add(your selectItem 3);
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-11-03
    • 1970-01-01
    • 2011-11-15
    • 1970-01-01
    • 1970-01-01
    • 2021-05-11
    • 2022-01-06
    • 2018-01-12
    相关资源
    最近更新 更多