<p>Xamarin.Forms.CollectionView 规范</p>

创建于 2018-06-27  ·  178评论  ·  资料来源: xamarin/Xamarin.Forms

集合视图

当前的 Forms ListView 设计和实现非常复杂且难以维护,同时通常无法提供用户想要的灵活性。 由于实现的复杂性和向后兼容性要求,ListView 错误可能很难找到和修复。

CollectionView 工作的目标是通过简化 API 和采用本机平台的列表构建控件的功能来解决这些问题。 为此:

  • CollectionView 完全删除了 Cells 的概念。 尽管在某些情况下很方便,但 Cell 概念在 ListView 的本机实现中引入了大量复杂性。 Cells 的所有可能都可以通过可重用的 DataTemplates 来完成。

  • CollectionView 减少了 API 表面。 来自 ListView 的几个属性和事件在 CollectionView 中不可用。 其中一些可以在 DataTemplates 中轻松替换; 其他人则非常特定于特定平台,并且从一开始就从未真正属于过。 可以在下面找到这些更改的列表。

  • CollectionView 旨在通过不对布局进行假设来更加灵活。 这使我们能够支持用户长期以来一直要求的布局(例如,Horizo​​ntalListView)以及本机实现已经提供的布局。

_注意:本文档中的任何内容均不应被视为当前 ListView 将被删除或将停止维护的指示。 这项工作只是旨在提供一种替代控件,它可以更轻松地满足许多 Forms 用户的需求。_

_注意:本规范中的任何内容都不能保证是最终的; 所有功能、实现和接口都可能发生变化。_

下面指定的功能的当前完成状态

支持API

为了向用户提供更现代的列表,CollectionView 工作将包括一些支持 API:

  • FontIconSource - 使用可缩放的字形作为图标; 目的是在 Forms 当前支持图像的地方支持字形。 这显然是 Forms 的许多部分中的理想功能,但在 CollectionView 中支持上下文滑动手势也是绝对必要的(请参阅FontIconSource 规范)。

  • SwipeView - 支持在元素上滑动以执行或显示进一步的操作(请参阅SwipeView 规范)。

布局规范

该规范为开发人员提供了指定项目是否以垂直列表、水平列表或网格布局的方式。 底层原生类都支持这些布局类型。 (请注意,在 iOS 上,此规范假定使用 UICollectionView 而不是 UITableView。)

提供给 CollectionView 的规范映射到每个渲染器中的本机布局。 例如,如果指定了网格布局,则在 iOS 上,渲染器将(默认情况下)使用 UICollectionViewFlowLayout。 在 Android 上,默认为 GridLayoutManager; 在 UWP、GridView 上。

Forms 不参与repeater 中items 的布局(除了生成items Views 本身); 这部分布局完全是原生的。

在每个渲染器中使用的布局方法的选择将由用户修改; 如果用户更愿意在 Android 上使用 StaggeredGridLayoutManager,则可以通过修改选择方法并返回所需的布局管理器来实现。

ListView API 删除

  • IsPullToRefreshEnabled - 现在由 RefreshView 处理。
  • IsRefreshing - 现在由 RefreshView 处理。
  • RefreshCommand - 现在由 RefreshView 处理。
  • HasUnevenRows - 现在是 ItemSizingStrategy。
  • RowHeight - 现在由要布置的第一个项目确定。
  • SeparatorVisibility - CollectionView 不包括内置分隔符; 用户可以在他们的模板中提供这些(如果需要)。
  • SeparatorColor - CollectionView 不包括内置分隔符; 用户可以在他们的模板中提供这些(如果需要)。
  • GroupShortName - 该属性的存在是为了支持跳转列表和语义缩放; CollectionView 阶段 1 不支持这些功能。

应用程序接口

上下文项

ContextItem 提供了一种指定上下文交互的方法,通常作为上下文菜单的一部分显示。

public class ContextItem
{
    public static readonly BindableProperty TextProperty;
    public string Text { get; set; }

    public static readonly BindableProperty CommandProperty;
    public ICommand Command { get; set; }

    public static readonly BindableProperty CommandParameterProperty;
    public object CommandParameter { get; set; }

    public static readonly BindableProperty IsEnabledProperty;
    public bool IsEnabled { get; set; }

    public static readonly BindableProperty IconProperty;
    public ImageSource Icon { get; set; }

    public event EventHandler Invoked;
}

特性

| API | 说明 |
| ------------- | ------------- |
| 文字 | 获取或设置显示在项目上的文本描述。 |
| 命令 | 获取或设置在调用此项时要执行的命令。 |
| 命令参数 | |
| 已启用 | 获取或设置一个值,该值指示用户是否可以与上下文项进行交互。 |
| 图标 | 获取或设置项的图形内容。 |

活动

| API | 说明 |
| ------------- | ------------- |
| 调用 | 当用户交互指示应执行此项表示的命令时发生。 |

上下文菜单

提供一种方法来指定要在上下文菜单中显示的一组交互。 可以为任何 VisualElement 提供 ContextMenu,并根据本机平台约定激活/显示。

public static class ContextMenu
{
    public static readonly BindableProperty MenuItemsProperty =
            BindableProperty.CreateAttached("MenuItems", typeof(ContextMenuItems), typeof(VisualElement));
}


public class ContextMenuItems : IList<ContextItem>
{
}

刷新视图

移至#5882

选择模式

为 CollectionView 提供选择模式行为。

public enum SelectionMode 
{
    None,
    Single,
    Multiple
}

SelectionChangedEventArgs

public class SelectionChangedEventArgs : EventArgs
{
    public IReadOnlyList<object> PreviousSelection { get; }
    public IReadOnlyList<object> CurrentSelection { get; }
}

特性

| API | 说明 |
| ------------- | ------------- |
| 上一个选择 | 获取在选择更改之前选择的项目列表。 |
| 当前选择 | 获取选择更改后选择的项目列表。 |

项目布局

用于指示实现类指定 CollectionView 用于排列其项目的布局的标记接口。

public interface IItemsLayout {}

ItemsLayoutOrientation

枚举ItemsLayout的可能方向。 随着项目的添加,CollectionView 在方向上扩展。

public enum ItemsLayoutOrientation
{
    Vertical,
    Horizontal
}

项目布局

表单提供的项目布局的基类。

public abstract class ItemsLayout : IItemsLayout
{
    public ItemsLayoutOrientation Orientation { get; }

    protected ItemsLayout(ItemsLayoutOrientation orientation);

    public static readonly BindableProperty SnapPointsAlignmentProperty;
    public SnapPointsAlignment SnapPointsAlignment { get; set; }

    public static readonly BindableProperty SnapPointsTypeProperty;
    public SnapPointsType SnapPointsType { get; set; }  

    public static readonly BindableProperty ItemSpacingProperty;
    public Thickness ItemSpacing {get; set;}
}

特性

| API | 说明 |
| ------------- | ------------- |
| ItemsLayoutOrientation | 指定 CollectionView 在添加项目时扩展的方向。 |
| SnapPointsType | 指定滚动视图时捕捉点的行为。 |
| SnapPointsAlignment | 指定捕捉点如何与视图中的项目对齐。 |
| 项目间距 | 指定每个项目周围的空白空间。 |

列表项布局

public class ListItemsLayout : ItemsLayout
{
    public ListItemsLayout(ItemsLayoutOrientation orientation) : base (orientation);

    public static readonly IItemsLayout VerticalList = new ListItemsLayout(ItemsLayoutOrientation.Vertical); 
    public static readonly IItemsLayout HorizontalList = new ListItemsLayout(ItemsLayoutOrientation.Horizontal); 
}

静态成员

| API | 说明 |
| ------------- | ------------- |
| 垂直列表 | 指定一个单列列表,其中的列表随着新项目的添加而垂直增长。 |
| 水平列表 | 指定一个单行列表,其中的列表随着新项目的添加而水平增长。 |

GridItemsLayout

定义多行或多列布局。

public class GridItemsLayout : ItemsLayout
{
    public static readonly BindableProperty SpanProperty;
    public int Span { get; set; }

    public GridItemsLayout([Parameter("Span")] int span, [Parameter("Orientation")] ItemsLayoutOrientation orientation) : base (orientation);
}

SnapPointsAlignment

枚举ListItemsLayout捕捉点的可能对齐方式。

public enum SnapPointsAlignment
{
    Start,
    Center,
    End
}

枚举值

| API | 说明 |
| ------------- | ------------- |
| 开始 | 捕捉点与项目的前缘对齐。 |
| 中心 | 捕捉点与项目的中心对齐。 |
| 完 | 捕捉点与项目的后缘对齐。 |

捕捉点类型

枚举ListItemsLayout捕捉点的可能行为。

public enum SnapPointsType
{
    None,
    Optional,
    Mandatory,
    OptionalSingle,
    MandatorySingle,
}

枚举值

| API | 说明 |
| ------------- | ------------- |
| 无 | 滚动不会对齐到项目。 |
| 可选 | 如果任何捕捉点足够接近,内容将捕捉到最接近的捕捉点,即滚动沿惯性方向自然停止的位置。 |
| 强制性 | 内容总是捕捉到最近的捕捉点,滚动会沿着惯性方向自然停止。 |
| 可选单| 行为与 Optional 相同,但一次仅滚动一项。 |
| 强制单人 | 与 Mandatory 的行为相同,但一次仅滚动一项。 |

特性

| API | 说明 |
| ------------- | ------------- |
| 跨度| 指定要在受约束方向上布置的项目数。 |

ItemSizingStrategy

提供可能被 CollectionView 使用的项目测量策略。

public enum ItemSizingStrategy
{
    MeasureAllItems,    
    MeasureFirstItem
}

枚举值

| API | 说明 |
| ------------- | ------------- |
| 测量所有项目 | 每个项目都是单独测量的。 |
| 测量第一项 | 只测量第一项; 假定所有后续项目与第一个项目的大小相同。 |

ItemsUpdatingScrollMode

定义常量,用于指定更新时项目的滚动行为。

public enum ItemsUpdatingScrollMode
{
    KeepItemsInView,
    KeepScrollOffset,
    KeepLastItemInView
}

枚举值

| API | 说明 |
| ------------- | ------------- |
| KeepItemsInView | 添加项目时,调整滚动偏移以保持视口中的第一个可见项目。 |
| 保持滚动偏移| 添加项目时,保持相对于列表开头的滚动偏移。 |
| KeepLastItemInView | 添加项目时,调整滚动偏移以保持视口中的最后一个可见项目。 |

集合视图

显示项目列表。

public class CollectionView : View
{
    public static readonly BindableProperty ItemsLayoutProperty;
    public IItemsLayout ItemsLayout { get; set; }

    public static readonly BindableProperty ItemsSourceProperty;
    public IEnumerable ItemsSource { get; set; }

    public static readonly BindableProperty ItemTemplateProperty;
    public DataTemplate ItemTemplate { get; set; }

    public static readonly BindableProperty ItemsUpdatingScrollMode;
    publio ItemsUpdatingScrollMode ItemsUpdatingScrollMode { get; set; }

    public static readonly BindableProperty HeaderProperty;
    public object Header { get; set; }

    public static readonly BindableProperty HeaderTemplateProperty;
    public DataTemplate HeaderTemplate { get; set; }

    public static readonly BindableProperty IsHeaderStickyProperty;
    public bool IsHeaderSticky { get; set; }

    public static readonly BindableProperty FooterProperty;
    public object Footer { get; set; }

    public static readonly BindableProperty FooterTemplateProperty;
    public DataTemplate FooterTemplate { get; set; }

    public static readonly BindableProperty IsFooterStickyProperty;
    public bool IsFooterSticky { get; set; }

    public static readonly BindableProperty EmptyViewProperty;
    public object EmptyView { get; set; }

    public static readonly BindableProperty EmptyViewTemplateProperty;
    public DataTemplate EmptyViewTemplate { get; set; }

    public static readonly BindableProperty GroupDisplayBindingProperty;
    public BindingBase GroupDisplayBinding { get; set; }

    public static readonly BindableProperty GroupHeaderTemplateProperty;
    public DataTemplate GroupHeaderTemplate { get; set; }

    public static readonly BindableProperty GroupFooterTemplateProperty;
    public DataTemplate GroupFooterTemplate { get; set; }

    public static readonly BindableProperty ItemSizingStrategy;
    public bool ItemSizingStrategy { get; set; }

    public static readonly BindableProperty IsGroupingEnabledProperty;
    public bool IsGroupingEnabled { get; set; }

    public static readonly BindableProperty SelectionModeProperty;
    public SelectionMode SelectionMode { get; set; }

    public static readonly BindableProperty SelectedItemProperty;
    public object SelectedItem { get; set; }

    public static readonly BindableProperty SelectedItemsProperty;
    public IList<object> SelectedItems { get; set; }

    public static readonly BindableProperty SelectionChangedCommandProperty;
    public ICommand SelectionChangedCommand;

    public static readonly BindableProperty SelectionChangedCommandParameterProperty;
    public object SelectionChangedCommandParameter;

    public static readonly BindableProperty RemainingItemsThresholdProperty;
    public int RemainingItemsThreshold { get; set; }

    public void ScrollTo(object item, object group = null, 
        ScrollToPosition position = ScrollToPosition.MakeVisible, bool animate = true);

    public void ScrollTo(int index, int groupIndex = -1, 
        ScrollToPosition position = ScrollToPosition.MakeVisible, bool animate = true);

    public event EventHandler<SelectionChangedEventArgs> SelectionChanged;

    public event EventHandler<EventArgs> RemainingItemsThresholdReached; 
}

特性

| API | 说明 |
| ------------- | ------------- |
| ItemsLayout | 获取或设置列表的布局规范。 |
| ItemSizingStrategy | 可以提供给控件以提高性能的用户提示。 如果将其设置为MeasureAllItems (默认值),则将单独测量每个项目。 在项目大小要统一的情况下,可以将此值设置为MeasureFirstItem ; 只测量第一个项目,所有后续项目将被赋予与第一个相同的尺寸。 |
| 项目模板 | 获取或设置用于显示每个项目的 DataTemplate。
| ItemsUpdatingScrollMode | 获取或设置一个值,该值指定更新项目时的滚动行为。 |
| IsGroupingEnabled | 获取或设置一个值,该值指示是否应按组显示基础数据。 |
| 标题 | 获取或设置将显示在控件顶部的字符串、绑定或视图。 |
| 标题模板 | 获取或设置用于设置标题格式的数据模板。 |
| IsHeaderSticky | 指定标题是否在用户滚动时保持原位。 默认为True |
| 页脚 | 获取或设置将显示在控件底部的字符串、绑定或视图。 |
| 页脚模板 | 获取或设置用于设置页脚格式的数据模板。 |
| IsFooterSticky | 指定页脚是否在用户滚动时保持原位。 默认为True |
| 空视图 | 获取或设置当 ItemsSource 为空时将显示的字符串、绑定或视图。 |
| 空视图模板 | 获取或设置用于设置 EmptyView 格式的数据模板。 |
| 组头模板 | 获取或设置组标题的 DataTemplate。 |
| 组页脚模板 | 获取或设置组页脚的 DataTemplate。* |
| 项目来源 | 要在控件中显示的对象列表。 |
| 选择模式 | 获取或设置控件的选择行为。 |
| 所选项目 | 为SingleSelectionMode获取或设置所选项目。 如果从项目源中删除所选项目,则SelectedItem将设置为null 。 |
| 选定项目 | 获取或设置SelectionModeMultiple的选定项目。 如果从项目源中删除所选项目,它们将从SelectedItems删除,并且SelectionChanged将被引发。 |
| 选择更改命令 | 获取或设置要在选择更改时执行的 ICommand。 |
| SelectionChangedCommandParameter | 获取或设置 SelectionChangedCommand 的参数。 |
| 组显示绑定 | 获取或设置用于显示组标题的绑定。 |
| 剩余物品阈值 | 指定将引发RemainingItemsThresholdReached事件的 CollectionView 中尚不可见的项目的阈值。 默认值为 -1,表示永远不会引发事件。 0,当显示ItemsSource当前的最后一个项目时将引发该事件。 当值大于 0 时,当ItemsSource当前包含尚未滚动到的项目数时将引发该事件。 |

方法

| API | 说明 |
| ------------- | ------------- |
| ScrollTo(object item, object group = null, ScrollToPosition position = ScrollToPosition.MakeVisible, bool animate = true) | 将指定的项目滚动到视图中。 |
| ScrollTo(int index, int groupIndex = -1, ScrollToPosition position = ScrollToPosition.MakeVisible, bool animate = true) | 将指定索引处的项目滚动到视图中。 |

活动

| API | 说明 |
| ------------- | ------------- |
| 选择已更改 | 当SelectedItemSelectedItems属性更改时引发。 这包括由于更改SelectionMode属性而发生的更改。 |
| RemainingItemsThresholdReached | 当 CollectionView 滚动到足够远以至于只有RemainingItemsThreshold项目尚未显示时引发。 可以处理此事件以加载更多项目。 |

场景

聊天应用

开发人员有一个带有聊天客户端的应用程序。 消息出现在列表底部并向上滚动屏幕。 开发人员如何使用建议的 API 实现此 UI?

为了实现此行为,开发人员应将CollectionView.ItemsUpdatingScrollMode属性设置为KeepLastItemInView 。 如果用户的滚动位置在 CollectionView 的末尾,新项目将出现在底部并滚动到视图中。 如果用户的滚动位置在别处,则新项目将出现在底部,但滚动位置保持不变。

捕捉到最近的

开发人员的应用程序显示了房地产列表。 当用户滚动列表时,滚动应该是平滑的,直到用户停止。 当滚动停止时,应用程序的界面应对齐滚动(动画),以便最顶部的列表与页面顶部完美对齐。 捕捉应始终在产生最少运动的方向上。

为了实现此行为,开发人员应使用具有以下设置的ListItemLayout

  • Orienation : Vertical
  • SnapPointsAlignment : Start
  • SnapPointsType : Mandatory

表视图

开发人员希望使用类似于 TableView 的外观重新创建设置页面。

开发人员将希望使用具有垂直方向的 ListItemsLayout。 ItemsTemplate 应设置为 DataTemplate,它重新创建表格单元格的外观。 如果“设置”界面旨在处理不止一种类型的设置(例如,如果某些单元格旨在打开/关闭设置,而其他单元格旨在导航到辅助设置屏幕),那么开发人员可能希望创建一个 DataTemplateSelector,它实现了一个用于开/关设置的 DataTemplate(带有一个切换开关)和一个用于导航的 DataTemplate(带有一个 TapGesture,它将辅助设置页面推送到导航堆栈上)。

无限滚动

开发人员有一个显示“新闻”提要的应用程序。 “新闻”提要具有无限数量的潜在项目,因此当用户接近当前加载的数据集的末尾时,应用程序需要对服务器进行异步调用以加载更多数据。 在用户看到空白区域或在网络延迟/带宽限制内停止滚动之前加载数据对应用程序至关重要。 开发人员如何使用建议的 API 实现这一点?

为此,开发人员应设置RemainingItemsThreshold属性并处理RemainingItemsThresholdReached事件。 引发事件时,处理程序可以对服务器进行异步调用,以将更多数据加载到底层ItemsSource

collectionview blocker roadmap enhancement ➕

最有用的评论

滚动事件如何支持视差标题

所有178条评论

滚动事件如何支持视差标题

这有很多值得爱的地方。

字体图标源

对于 FontIconSource,虽然我们确实需要一种不使用 Unicode 值的方法(如果我们不想的话)。 如果您正在查看值为f370的 FontIconSource,您将完全不知道它应该是什么。

另一方面,如果我可以选择我正在使用的图标字体,并为 Forms 提供一种将fa-app-store-ios转换f370的 unicode 的方法,现在我可以一目了然我使用的图标来自 Font Awesome,它是 iOS App Store 图标。 我绝不是说表单应该对所有可用的字体(或任何相关的)都有这种理解,可以来自一些公共要点或添加到社区工具包等。无论哪种方式,我们都需要一个使用有意义的名称的方法。

最后,我希望我们可以为此在 XAML 扩展中进行烘焙,因此您可能有以下内容:

<Image Source="{FontIcon fa-app-store-ios,Color={StaticResource primaryColor}}" />

菜单

正如我之前与@davidortinau讨论的那样,如果我们可以在上下文菜单上混合搭配以获得适当的结果,那将是特别理想的。 关于这方面的一些很好的背景是考虑一个电子邮件客户端,您可以在其中向左滑动时获得一个菜单,而在向右滑动时获得另一个菜单。 我希望看到支持的另一种情况是像iOS CollectionView的文档中所示的单元格菜单方法。

活动

我认为可以肯定地说我有偏见,但是社区中有很大一部分人遵循 MVVM 设计模式。 拥有SelectionChangedRemainingItemsThresholdReached事件对 API 都很重要,但如果我们能找到一种方法来支持这些 OOB 与事件处理程序的 ViewModel 版本,那就太棒了......我命令。

由于 RemainingItemsThresholdReached 只是发送一个普通的旧 EventArgs,我认为我们可以安全地假设将 null 传递给命令应该没问题,因为我们只需要执行命令。 对于 SelectionChanged,我倾向于认为了解新项目与旧项目相比更为重要,因此只需将新项目 OOB 传递给 SelectionChangedCommand 就可以了。 这可能不会影响每个用例,但它至少提供了开发人员需要添加一些 EventToCommandBehavior 的最小开销。

杀死当前列表视图的完美示例正在制作日历控件,其中:
-days(单元格)可以有多种样式:
作为促销日,生日,残疾人/无销售日/银行假期......
带有不同自定义字体的嵌入图标,如果选中,单元格有阴影,在 r 时为其他样式
愤怒,其他在范围开始和结束时
- 可以选择日期范围
- 月份标题和自定义标题样式
-month 标题具有允许在当月进行某些特殊视图/操作/显示的按钮

添加一个 GroupFooterTemplate 怎么样?

这在 Forms 中非常需要:-) CollectionView 将消除昂贵的解决方法,解决限制,并可能提高我在过去 5 年中制作的几乎每个 Forms 应用程序的性能。 也是完全正确的方法 - 利用并展示本机平台的力量。

如果我只能要求对 Forms 进行一项改进,那就是它。
(实际上,我是在 2017 年回应@davidortinau 的)

这真是太棒了,期待已久! API 简洁明了(感谢您重命名 HasUnevenRows !)。

正如@dhaligas 所建议的那样,非常需要滚动事件。 例如,对于视差动画以及在滚动时隐藏浮动操作按钮。

FontIconSource 是个好主意。 提供一个默认的图标列表可能会很好,每个平台都映射了 unicode(类似于 iOS 或 UWP)。

这听起来正是所需要的。 API 看起来更简洁,以这种方式构建多个视图/容器应该有助于保持代码更清晰和更简单。

到目前为止我的评论:

@dansiegel欢迎在满足剩余项目阈值时执行命令。 但不确定 SelectedItems 是否需要它 - 只要 SelectedItems 是 ObservableCollection(或任何实现 INotifyCollectionChanged 的​​东西),您所说的一切(更改通知、更改内容,甚至原因)都会自动处理。 我宁愿在 CollectionView 中使用尽可能少的代码来降低复杂性。

滚动:我完全同意滚动事件。 我们现在可以在 Android 上获得它,但是对于 iOS,您必须包装 UITableViewSource 并劫持 Scrolled 方法。

对我来说最重要的是可扩展性。 请不要为适配器和 TableViewSource 使用内部类,并且请在本机渲染器中公开“CreateAdapter”和“CreateViewSource”方法(对于其他平台也类似),如果我们愿意,我们可以在其中创建自己的类型。 我们有一个自定义 ListAdapter 用于在 Android 上支持拖放,并且如前所述,一个自定义 UITableViewSources 用于滚动和拖放。 这不是我喜欢的代码,因为有内部类等的包装。

这不仅适用于适配器/视图源。 一般来说,在新 API 中,如果需要,请添加可以扩展行为的点。

我认为这是一个非常棒且重要的功能!
iOS 已经在使用 UICollectionView 名称,这可能会导致在搜索 CollectionView 时出现混淆和错误的谷歌结果。 这是一个问题吗?

只是为了摆脱它,我基本上喜欢关于CollectionView规范的所有内容。 不过,可能值得将某些事情拆分成单独的问题,因为我对它们有想法,因为我相信很多其他人也有想法,而且我可以看到对话越来越难以理解。 例如:

这可以稍后添加,但类似于:

public class MultipleFontIconsSource : ImageSource
{
    public List<FontIconSource> Icons { get; set; }
}

会很有用,支持堆叠图标: https :

我的反馈:

  1. 我不会将项目选择功能放在 CollectionView 类中。 相反,我会添加一个从 CollectionView 派生的抽象基类 ListCollectionView ,它具有特定的功能:
public class CollectionView : View
{
   // Common capabilities related to a view capable of displaying a list of items
    public static readonly BindableProperty ItemsLayoutProperty;
    public IItemsLayout ItemsLayout { get; set; }

    public static readonly BindableProperty ItemsSourceProperty;
    public IEnumerable ItemsSource { get; set; }
}

public class ListCollectionView : CollectionView
{
     // Item selection capabilities and other capabilities 

    public static readonly BindableProperty SelectionModeProperty;
    public SelectionMode SelectionMode { get; set; }

    public static readonly BindableProperty SelectedItemProperty;
    public object SelectedItem { get; set; }

    public static readonly BindableProperty SelectedItemsProperty;
    public IList<object> SelectedItems { get; set; }

    public static readonly BindableProperty SelectedItemsProperty;
    public IList<object> SelectedItems { get; set; }
}

我的想法是拥有一个类似于 Windows XAML 中的 ItemsControl 的 CollectionView。 ItemsControl 采用一个 Panel 实例来定位项目。 在 Forms 中,我们将拥有 CollectionView 和 IItemsLayout。
默认情况下,如果未给出 IItemLayout,则默认布局可以是堆栈布局。 通过这种方式,我们基本上可以将 ItemsSource 与来自 Windows XAML 的 StackPanel 结合起来,或者换句话说,一个可绑定的 StackLayout !

除了项目选择之外,还有其他功能我不会放在 CollectionView 中,我会将这些添加到 ListCollectionView。 例如,CollectionView 不应该滚动。 这样它将涵盖这个线程

  1. 我将 IItemsLayout 接口重命名为 ICollectionViewLayout。 该框架已经有LayoutItemsView 。 这将是一个更长的名称,但 ICollectionViewLayout 强烈表明它的用途,它特定于 CollectionView,而不是显示项目的某种通用方式。

  2. 我将 ItemsLayout 类重命名为 OrientedCollectionViewLayout。 这有力地表明了抽象基类的真正用途,所有派生类都以面向对象的方式布局项目。 此外,在名称中使用“Oriented”可以在将来添加一个名为“CollectionViewLayout”的抽象基类。 如果所有集合视图布局类都需要一些新的通用功能,而不仅仅是具有方向的那些。

  3. 删除 ViewCell 并只使用 DataTemplate 是非常受欢迎的,它提高了可重用性。

  1. 你能分享更多关于 RefreshView 的细节吗?
    我认为 RefreshView 应该以某种方式映射到 iOS 上的 UIRefreshControl? 它将如何在 Android 和 UWP 上运行?

如果有人感兴趣,我对上面的第一条评论进行了一些更新。

我同意@andreinitescu 的观点,即有一种非滚动集合的方法会很好。 我对这是否意味着将其分解为多个类或可能具有 ScrollMode 属性之类的内容持中立态度。 我会尊重那些比我自己拥有更多 API 设计经验的人。 但是使用 DataTemplate 或模板选择器实现您自己的基于 StackLayout 的项目列表是相当简单的,所以可能不需要它。

虽然我喜欢控制滚动功能的想法,但我也没有想出任何引人注目的非滚动“集合”用例,其中包括 ListView 的所有高级功能或建议的 CollectionView。 我的非滚动列表用例一直由琐碎的项目列表解决。 我不使用 ListView 的正常原因是因为我不想选择或我想水平布局列表。 提议的规范似乎涵盖了这两种情况。 我会对任何其他人没有滚动的任何使用示例感兴趣。

@bmacombe我同意你的观点,实现可绑定的 StackLayout 是“简单的”,但这不是我认为的重点。 这是一个非常常见的功能,为什么不在框架中包含它? 有了一些计划,我认为这是可以做到的。 就像我上面已经说过的那样,它可以通过将功能分散到两个类中来解决,一个基类(类似于 Windows XAML 中的 ItemsControl)和 CollectionView (ListView)。 理想情况下,层次结构中应该有一个 Selector 类(请参阅 https://docs.microsoft.com/en-us/uwp/api/windows.ui.xaml.controls.primitives.selector)

我想说有一个非滚动选项的微不足道的原因是一些页面需要有一个 ScrollView 整个页面,以及一个项目列表。

如果这样做,现在不建议将 ListView 放在 ScrollView 中。 一个可以放在那里的可绑定 CollectionView,它仍然可能具有 ListView 的所有功能,这是我多次需要的东西。

我写了与其他人一样的 BindableStack 东西,但是一个烘焙的东西会更好用。

@adammeaney这是有道理的,我现在考虑过类似的事情。

@andreinitescu我不反对将它内置会很棒。我认为每个人都在同一页面上了解所需的内容,以及如何最好地做到这一点。 只要有某种类型的“无滚动”选项,我对任何一种方法都可以。

在我自己的框架中,我总是来回将许多功能构建到一个控件中,或者有许多具有增量功能的类似类。 我会很高兴,但是 Forms 团队决定最好地实现它,特别是考虑到底层平台实现。

@bmacombe通过一些计划,我希望我们可以用一颗石头得到两只鸟。
例如,以我提到的方式工作的 CollectionView 类的实例,如果它没有设置 IItemLayout,它可以通过渲染器机制映射到 iOS 上的本机 UIStackView 或 UWP 上的 StackPanel 或 Android 上的 LinearLayout。 或者,为了更容易实现,它可以只使用现有的 StackLayout 来排列视图。

我的印象是,一个新的 ListView 既应该解决现有 ListView 的挑战,又应该为此处的“RepeatableBinder”线程提供解决方案

在推进这个规范之前,我们想看看 ListView2 在哪里。 它包含许多相同的所需组件,最好避免重复它们。

我不明白如何将所有功能放在 CollectionView 中,就像这里的规范所建议的那样会正确地完成工作。

2680 可以添加到此规范中吗? 关于 ScrollBar 启用。

@andreinitescu

你能分享更多关于 RefreshView 的细节吗?
我认为 RefreshView 应该以某种方式映射到 iOS 上的 UIRefreshControl? 它将如何在 Android 和 UWP 上运行?

在 UWP 上,我们可能会使用RefreshContainer 。 在 Android 上,可能是SwipeRefreshLayout

@krdmllr

iOS 已经在使用 UICollectionView 名称,这可能会导致在搜索 CollectionView 时出现混淆和错误的谷歌结果。 这是一个问题吗?

这是一个问题,但不是一个新问题。 我们在 GestureRecognizer、ListView、Grid 和 Forms 中的许多其他东西上也有同样的问题。 我们在内部遇到了一些困难; “屏幕上的一堆项目”只有这么多可能的名称。

“CollectionView”与我们当前在 Forms 中拥有的任何内容都没有冲突,它与任何 UWP 控件名称都不冲突(就像“ListView”那样),并且它与 UICollectionView 不完全相同(因为有“UI”前缀)。 对于搜索目的来说,它不是 100% 理想的,但我们认为它是控件意图的最佳表达。

也就是说,如果有人提出了一个我们立即爱上的替代名称,我很乐意进行搜索和替换。

(我想将其命名为“ListView2ColonRevengeOfTheListView”,但@davidortinau 击倒了我:))

@丹西格尔

关于这方面的一些很好的背景是考虑一个电子邮件客户端,您可以在其中向左滑动时获得一个菜单,而在向右滑动时获得另一个菜单。

看看SwipeView 规范——这正是我们的目标。

@GalaxiaGuy

支持堆叠图标

这是一个很好的观点,如果可能,我们应该支持这一点。 我知道它适用于内置的 UWP 字形; 我必须做一些研究以确保这种类型的堆叠可以在其他平台上工作(我怀疑答案是“是”)。

更新:此规范的 FontIconSource 部分已移至其自己的规范中

我会从一个选择中选择多个项目的用户场景,例如从相册中选择一张或多张照片。 OneDrive 或 WhatsApp 等应用程序中很常见的场景。

20180527_181626000_ios

@hartez

也就是说,如果有人提出了一个我们立即爱上的替代名称,我很乐意进行搜索和替换。

由于不同的原因,我已经建议了一个新名称

SelectionModeMultiple时, SelectedItem的值是多少? 我能想到的有5种选择:

  1. 按选择顺序最后选择的项目。
  2. 按来源顺序最后选择的项目。
  3. 按选择顺序最后选择/取消的项目。
  4. 按来源顺序最后选择/取消的项目。
  5. 空值



    (2), (3) 和 (4) 不是很有用。 我添加它们只是为了涵盖所有选项。 (1) 似乎是最合乎逻辑的选择。 (5) 如果您根本不想支持SelectedItem如果SelectionModeMultiple

@AmrAlSayed0

当 SelectionMode 为 Multiple 时,SelectedItem 的值是多少?

现在的答案是“无论在您将SelectionMode切换到Multiple之前是什么”。

@rogihee

我想从一个选择中多选择项目的用户场景

请问这个选择场景是否支持? AFAIK,我们打算使用的所有本机控件都支持它,因此在 CollectionView 中_应该_支持它。

SelectionMode 的可绑定样式将很有用,如果 SelectionMode=None、Transparent 等,这是 Radlist 所做的非常有用的、基于绑定处理视觉状态的简单方法。 每种选择模式的样式将涵盖这些场景。

@andreinitescu

回应来自https://github.com/xamarin/Xamarin.Forms/issues/3172#issuecomment -401015625(和其他地方)的评论:

你提出了很多优点,我想确保你知道我们没有忽视它们。 我们只是还不知道所有的答案。 我们正在开发这个 API,以便我们可以看到它在哪里工作以及它在哪里崩溃; 我怀疑您建议的课程细分非常接近我们需要结束的地方。

我们认识到您(和其他几个人)非常希望将这些中间类呈现为模板化项的 StackLayout 和网格(即“BindableRepeater”),这是我们正在探索的用例之一。

@亚历克斯哈德威克

一般来说,在新 API 中,如果需要,请添加可以扩展行为的点。

渲染器中的UpdateX方法将是protected virtual 。 :)

严肃地说,我们知道这在过去一直是一个痛点,我们在编写CollectionView时牢记这一点。

  1. 再想想,我真的不认为 CollectionView 是这个视图的类名的好选择。
    在 Windows XAML 中,CollectionView 是用于筛选分组的项目数据源的基类,请参阅https://msdn.microsoft.com/en-us/library/system.windows.data.collectionview (v=vs. 110).aspx
    也许在某个时候 Xamarin Forms 会获得一个用于相同目的的类,我认为如果它具有相同的名称 (CollectionView) 是有意义的,尤其是在考虑 XAML 标准时(这是否仍在计划中?)

    听起来既丑陋又有趣,ListView2 是一个不错的选择:) 当现有名称是唯一有意义的名称时,建议在 .NET 中使用后缀进行版本控制:

    务必使用数字后缀来表示现有 API 的新版本,特别是如果 API 的现有名称是唯一有意义的名称(即,如果它是行业标准)并且添加任何有意义的后缀(或更改name) 不是一个合适的选项。

    _框架设计指南:可重用 .NET 库的约定、习语和模式,第 2 版_
    https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/general-naming-conventions

    在以后的某个时候,每个人都会使用新的、闪亮的。 稳定且高性能的 ListView2 :)。 快进,将 ListView2 重命名为 ListView,虽然是一个突破性的变化,但对每个人来说都将是简单(并且受欢迎)的重构。

  2. 在 Xamarin Forms 中已经有一个 ItemsView它看起来非常类似于 Windows XAML 中的 ItemsControl,只是它没有项目布局属性。
    不是创建一个新的 CollectionView 类,而是可以使用现有的 ItemsView也作为新 ListView 的基类?

  3. 在 API 设计和实现中存在一个明显的挑战,使用显示列表项的本机平台控件,但仍然可以灵活地使用“BindableRepeater”之类的东西,它旨在显示一个简单、更轻、不可滚动和非- 可选择的项目列表。
    似乎 Uno 设法做到了:

是否可以将现有的 ItemsView 也用作新 ListView 的基类,而不是创建新的 CollectionView 类?

ItemsView<T> ,但我们不想使用它。 它使用TemplatedItemsList ,这是我们试图通过这个新控件避免的一部分。

在以后的某个时候,每个人都会使用新的、闪亮的。 稳定且高性能的 ListView2 :)。 快进,将 ListView2 重命名为 ListView,虽然是一个突破性的变化,但对每个人来说都将是简单(并且受欢迎)的重构。

你的乐观是迷人的,但我们必须在 ListView(1) 是永远存在的假设下工作,并且不允许像 ListView2 重命名这样的重大更改。

我认为与 Windows XAML 相提并论是有道理的,但好吧,只要新控件符合其承诺,就可以使用任何您想要的名称。 Uno 框架似乎已经成功地做到了这一点,所以现在我很想看看你们在 Xamarin Forms 中带来了什么。

@gmwilhelm

https://github.com/xamarin/Xamarin.Forms/issues/3172#issuecomment -400925994

好点子。 我暂时将其添加到 API 中。 我试探性地说,因为我完全可以看到我们如何在 iOS 和 Android 上实现它,但 UWP 可能具有挑战性。

但我不能否认它既合理又令人愉悦的对称。

添加GroupItemsBinding怎么样?

这将使 Group包含一个集合类型属性,而不是像 ListView 那样要求一个组派生自一个集合。 这个现有的 ListView 限制迫使我多次对分组数据结构进行性能昂贵的复制。 添加GroupItemsBinding将防止这种情况并允许更灵活地映射到分组数据结构。

GroupDisplayBinding 文档中使用的示例可能是:

```C#
class Group // 注意 Group 不必从 ObservableCollection 派生
{
公共组(字符串 firstInitial){ FirstInitial = firstInitial; }

public string FirstInitial { get; private set; }

public ObservableCollection<Person> Persons { get; set; } // We use a property for the group items instead

}

ListView CreateListView()
{
var listView = 新的 ListView {
GroupItemsBinding = 新绑定 (nameof(Group.Persons))
// ...
};
// ...
}

``

鉴于这是 UICollectionView 在布局方面所做的一个子集,我觉得我们应该选择一个不同的名称以避免与控件中的功能混淆。

需要明确的是,此控件尚不可用,是否正确? 我试图引用它,但我的项目找不到它

@titonton这个问题只是为了讨论 CollectionView 的规范,实现还没有开始,我认为在规范完成之前不会。

@AmrAlSayed0实际上它应该已经开始了,因为它在 11 天前被移至“Sprint 139 中的进行中”。

鉴于不清楚 API 的决定是什么,目前还不清楚这是如何开始的

@opcodewriter这就是我的想法。 @AmrAlSayed0感谢您的澄清。

有人可以澄清这个规范的当前状态吗? 社区可以提供帮助的地方是否缺少某些东西?

@migueldeicaza @hartez如果您不想将其命名为CollectionView这将很难命名。 CatalogView怎么样?

1

目录通常设计在一列或多列中,并包含多行具有相似字体、文本、布局等的项目。

样本:

022

@hartez您是否觉得 API 现在已接近完成? 到目前为止,在这方面做了多少工作? 我们中的许多人都希望尽快掌握这种控制。 :)

@adrianknight89我相信这是工作分支。 https://github.com/xamarin/Xamarin.Forms/tree/lv2spike

我们预计它暂时还没有准备好进行预览,但我将在未来几周内展示/演示当前工作的结果,以验证进度并及时反馈。

我糊涂了。 由于您已经有一些内部演示,听起来您已经离实现很远了。
这不应该意味着许多 API 已经确定了吗? 您是否遵循此处的 API 规范?
我看不出当前的规范将如何解决这里和这里的另一个线程上讨论的内容https://github.com/xamarin/Xamarin.Forms/issues/1718
更准确地说,API 不够灵活,无法允许例如简单的不可滚动和可绑定的类似 StackLayout 的控件。

新控件是否允许像 StackLayout 一样在没有滚动条的情况下将绑定项放在堆栈中?

谢谢等了好久👍

经过大量内部讨论并尝试找出合适的架构后,我们决定 CollectionView 将_不_处理#1718 中讨论的布局场景。 换句话说,它不会处理将对象集合绑定到任何 Xamarin.Forms 布局中的项目。

CollectionView 的最初目标是允许用户轻松利用各种现代原生列表/网格控件(UICollectionView、RecyclerView、ListView/GridView 等)。

尝试使 CollectionView 成为满足每个人“使用数据渲染和排列此模板”需求的一站式控件是很诱人的,包括所有“排列”步骤由表单布局(FlexLayout、StackLayout 等)处理的场景。 )。 并且有一些明显的功能重叠(例如,两个场景都使用 DataTemplates)。 但最终,它们在基础架构上存在很大差异,尝试将它们连接在一起会导致比简单地将它们作为单独的控件更难维护和混淆的事情。 我们不想创建如此复杂的东西,以至于我们最终不得不在几年内实现 ListView3。 我将在下面详细说明。

这样做的结果是,CollectionView 将继续关注允许 Forms 用户利用本地列表/网格控件并从他们的布局引擎和虚拟化中受益的问题。 并且 #1718 将更新以反映一个 API,该 API 将允许表单用户将ItemsSourceItemTemplate绑定到各种表单布局引擎。

对于那些对两个控件与一个控件的_为什么_感兴趣的人:

此处概述的内容(作为 CollectionView)与 #1718 中的建议之间的根本区别在于布局发生的位置。

CollectionView 旨在使用本机布局引擎(平台开发人员对其进行了大量优化)来处理布局。 一些来自 Forms 的自定义代码被涉及(例如,在 Android 和 iOS 上提供像 SnapPoints 逻辑之类的东西),但在大多数情况下,原生布局引擎(和原生虚拟化实现)正在做繁重的工作。 这对性能产生了巨大的影响。

因此,开发人员提供给 CollectionView 的任何布局信息都只会传递给每个平台上的渲染器进行解释; 它实际上是一个翻译成本地语言的规范(Android 上的 LinearLayoutManager/GridLayoutManager、iOS 上的 UICollectionViewFlowLayout 等)。 除了 DataTemplate,Forms 不做任何布局工作。

相比之下,Forms Layout(FlexLayout、StackLayout、AbsoluteLayout 等)完全布局在 Forms 层中。 表单布局的渲染器做的很少。 并且没有发生虚拟化; 所有项目从一开始就创建并放置在布局中。

试图将这两件事联系在一起会导致一些棘手的问题,包括:

  1. 渲染器映射如何工作? 使用 StackLayout 的 CollectionView 与需要使用 RecyclerView 的 CollectionView 具有非常不同的渲染器。 当我们不需要它时,我们是否将它们混合在一起并隐藏 RecyclerView? 我们有从 DefaultRenderer 派生的渲染器吗? 如果我们这样做,我们总是有一个我们并不真正需要的额外的 ViewGroup 层......

  2. 我们如何处理 ScrollView? UICollectionView 处理自己的滚动显示,但如果 StackLayout 需要滚动,用户通常会在 Forms 中手动添加它。 如有必要,我们是否添加另一层以自动插入滚动? 如果布局需要 UICollectionView,我们是否禁用/删除手动添加的 ScrollView?

  3. 就此而言,ScrollTo 方法在哪里?

... 等等。 所有这些问题都是_可解决的_,但每个解决方案都会增加_复杂性_。 正如#1718 中指出的那样,将 ItemsSource 和 ItemsTemplate 添加到表单布局并不是那么困难或复杂。 仅仅将这两个不同的场景连接在一起而变得复杂是不值得的。

我糊涂了。 由于您已经有一些内部演示,听起来您已经离实现很远了。 这不应该意味着许多 API 已经确定了吗? 您是否遵循此处的 API 规范?

我们正在关注此处发布的 API。 “相当远”可能是夸大其词; 到目前为止,我们已经实施了规范中一些没有争议的部分,以验证它们是可能的,并且我们不会走上任何死胡同。 假设我们没有遇到任何问题,到目前为止我们实现的大部分内容都可能在发布版本中。 但是规范中的所有内容仍然会发生变化,到目前为止我们已经实现的所有内容也是如此。

我看不出当前的规范将如何解决这里和这里的另一个线程 #1718 上讨论的内容。 更准确地说,API 不够灵活,无法允许例如简单的不可滚动和可绑定的类似 StackLayout 的控件。

是的,我们一直在努力的一部分是确定 CollectionView _could_ 是否合理地涵盖了这些用例。 我们已经就此做出了决定; 见https://github.com/xamarin/Xamarin.Forms/issues/3172#issuecomment -424413234。

鉴于这是 UICollectionView 在布局方面所做的一个子集,我觉得我们应该选择一个不同的名称以避免与控件中的功能混淆。

正如我所说的(https://github.com/xamarin/Xamarin.Forms/issues/3172#issuecomment-401186893),我对其他名字持开放态度。

目录视图怎么样?

目录通常设计在一列或多列中,并包含多行具有相似字体、文本、布局等的项目。

这是一个有趣的想法。 它绝对不会与任何现有的控件名称冲突。

@hartez作为互联网上的一个随机人,他越来越熟悉 Xamarin Forms 的内部结构(并且已经非常熟悉 UITableView 和 UICollectionView),我认为这是正确的举措。

是否仍然可以提供自定义布局(即使这意味着为每个平台提供单独的实现)?

是否仍然可以提供自定义布局(即使这意味着为每个平台提供单独的实现)?

绝对地。 您可以提供自己的带有 IItemsLayout 标记的布局,并且您的自定义渲染器可以根据需要对其进行解释。

例如,作为概念验证,我为 CollectionView 继承了 Android 渲染器,并添加了解释类FlexLayout : IItemsLayout的能力,该类包含一堆 Flex 布局属性。 它将这些属性传递给 Google 的FlexBoxLayoutManager ,并将该布局管理器与 RecyclerView 一起使用。 一旦我们提供了一个公共预览版,我可能会把这个例子放在 GitHub 上,这样人们就可以轻松地参考如何做这样的事情。

目的是让这个东西非常非常灵活。

@hartez
https://github.com/xamarin/Xamarin.Forms/issues/3749 中描述的问题是否已通过 CollectionView 修复?
因为在这里我看到CollectionView只有ItemTemplate属性,这听起来像ListView一样会有同样的问题。

@hartez
#3749 中描述的问题是否已通过 CollectionView 解决?
因为在这里我看到CollectionView只有ItemTemplate属性,这听起来像ListView一样会有同样的问题。

@andreinitescu感谢您指出该讨论,我不知道 DataTemplate 存在这个问题。

下周我将花一些时间研究 DataTemplate 的历史——为什么它是这样设计的,以及修复CreateContent以自动做正确的事情是否存在任何向后兼容性问题(两者都在ListView 和 CollectionView)。

@hartez仅作为我在创建自己的中继器控件时如何解决此问题的示例。

//检查我们是否有模板选择器或只是一个模板
var templateToUse = itemTemplate 是 DataTemplateSelector templateSelector 吗? templateSelector.SelectTemplate(item, null) : itemTemplate;

所以在这种情况下,仅仅修复 CreateContent 不会破坏它,只是让它变得不需要。 但我确实同意@andreinitescu将 ItemTemplate 和 ItemTemplateSelector 作为单独的属性分开是理想的……可能是因为我的 WPF 和 SL 背景。

@bmacombe恕我直言,这不仅是将其与 WPF/SL 对齐的偏好问题,这确实是一个问题,它造成了混乱。 见#3544

@andreinitescu它确实造成了混乱:) 相信我,当我试图在我的中继器中支持 DataTemplate 和 DataTemplateSelector 时,我一开始很困惑! 特别是当我将 DateTemplateSelector 分配给我的 DataTemplate 属性时出现错误时,它在所有使用它的 XF 位置都有效。 挖掘了一些源代码来解决这个问题。 对于仅使用内置 XF 控件的人来说,可能不是问题,但是尝试拥有并使用它……真的很令人困惑。

我们可以在 CollectionView 上设置滚动事件吗? 在 CollectionView 发布之前,我对 ListView 有一个建议https://github.com/xamarin/Xamarin.Forms/issues/4323

并且,是否可以创建不规则和动态布局,例如 PInterest:

你看,每个图像都有自己的高度:-)

不确定可以支持这种布局吗?

image

更新:从名称提案列表中,我们提出的最接近的是“ItemsView”,这是为了避免使用术语“CollectionView”,让人们觉得这与 iOS 的“UICollectionView”一样完整

您好,我还是 Xamarin 的新手,但一直在使用 DataTemplateSelector 处理 ListView。
当我尝试使用 CollectionView 和 DataTemplateSelector 进行测试时,它抛出错误

未处理的异常:

System.InvalidOperationException: LoadTemplate 不应为 null

是否存在与 DataTemplateSelector 相关的已知错误?
我可能会错误地实施它。 有没有关于在 CollectionView 中使用 DataTemplateSelector 的例子?

@hartez @davidortinau为何没有将KeepItemsInView命名为KeepFirstItemInView以与KeepLastItemInView保持一致? 当前名称是复数(即建议多个项目),而描述说它只保留视口中的第一个可见项目。

另外,有没有一种方法可以公开 API 来获取当前在视口中的视图列表? 前几天晚上,我正在创建一个视频视图以嵌入ListView单元格并根据视口可见性自动播放/暂停,但使用当前的ItemAppearingItemDisappearing几乎是不可能的CollectionView以更可靠的方式支持这种功能。

autoplayvideos demo

另一件很棒的事情是能够创建一个依赖的、最小化的视图,该视图与父视图分离,同时用户可以在当前提要上滚动。 我在 YouTube 上看到了这一点,因为我们现在可以继续观看当前视频,同时可以继续浏览。 我不确定这是否CollectionView可以或应该支持 btw,但这是需要考虑的。

youtube1-5abab8210e23d9003787855d

所以我玩了一下当前的每晚构建(4.0.1.43780-nightly),与当前的预览构建相比,它解决了一些调整大小的问题。

我的一个建议是将 RowSpacing/ColumnSpacing 或 GridSpacing 之类的内容添加到网格布局中,因为这样可以更轻松地正确分隔您的项目,而无需在单个项目上使用边距/填充。
另一件事是将 Padding 或 EdgeOffset 添加到 CollectionView 或 Layout 以避免使用 Margin,它会切割如下所示的项目:
android-margin-image
Margin 还会在 Android 上裁剪“拖动”动画,如下所示:
android-margin

我的一个建议是将 RowSpacing/ColumnSpacing 或 GridSpacing 之类的内容添加到网格布局中,因为这样可以更轻松地正确分隔您的项目,而无需在单个项目上使用边距/填充。

同意,这在我们的雷达范围内 - 参见 #4681。

更新:从名称提案列表中,我们提出的最接近的是“ItemsView”,这是为了避免使用术语“CollectionView”,让人们觉得这与 iOS 的“UICollectionView”一样完整

“浮动视图”怎么样?

除了上面提到的 ItemAppearing/Disappearing 事件之外,任何获得项目视图的方法的计划:
View GetView(object item)
如果项目没有具体化,我猜它应该返回 null。

我正在使用垂直列表,它在 iOS 和 Android 上的呈现方式似乎不一致。

在 iOS 上,带有标签的将占据 100% 的宽度。
screenshot 2019-01-15 13 56 01

在 Android 上,它只会占用它的内容宽度。
screenshot 2019-01-15 13 57 59

我只能使用静态宽度定义使其正确布局。
是否有尊重 Grid Width="Auto"属性的 Android 解决方法?

我正在使用垂直列表,它在 iOS 和 Android 上的呈现方式似乎不一致。

@shwanton请为此错误打开一个单独的问题,我会看看。

@shwanton我有类似的问题,当我切换到夜间提要时得到了解决

@krdmllr我可以确认,它已在最新版本中修复。 谢谢你。

你好。 CollectionView 中会不会有类似于 ListView 的 ItemTapped 的 ItemTapped 事件? 我在规范中没有看到它。 谢谢你。

@uvirra您的DataTemplateSelector查询存在问题。 见#4826。

@hartez是否需要像ListView存在的三个项目回收策略? 您确实多次提到CollectionView利用的本机虚拟化。 我只是想对此得到更多澄清。

我也很想知道RefreshView在 iOS 上的外观。 ListView的当前刷新需要打开UITableViewBounces属性,而在 Android 上,刷新视图被拉到最显眼的项目(即我个人更喜欢)。

@hartez是否需要像ListView存在的三个项目回收策略? 您确实多次提到CollectionView利用的本机虚拟化。 我只是想对此得到更多澄清。

当前的设计不需要任何类似回收策略的东西。 现在,我们只是利用本机控件提供的虚拟化,它开箱即用地完成了很好的工作。

会有需要吗? 我的希望是“不”,我们将尽最大努力避免它,因为它增加了很多复杂性(对用户和维护而言)。 如果我们最终得出结论,我们需要这样的东西,我们将非常非常仔细地进行设计。

滚动事件呢? 大多数现代 UI/UX 都提供视差标题、滚动时显示/隐藏项目(按钮、标题、过滤器等)等。
我认为像这样的新的、惊人的控件应该支持现代场景。

这应该不是问题,recyclerview 和 UICollectionview 都支持开箱即用的滚动事件。

甚至 Carouselview(基于 collectionview)也支持带有方向、滚动值和增量的滚动事件: https :

为了跟进@Evolutionlab对这是一个应该支持现代场景的新的惊人控件的评论,我希望看到更好的虚拟化支持。

https://docs.microsoft.com/en-us/windows/uwp/debug-test-perf/listview-and-gridview-data-optimization

如果这太难理解了,我想访问 VisibleItems,以便我可以在我的 ViewModel 中进行虚拟化。

继续伟大的工作!

@hartez我只是认为让开发人员定义所选项目数量的最小/最大阈值会很酷。 我目前正在制作一个自定义照片库,不允许选择超过 5 张照片。 当达到阈值时,应忽略单元格上的点击事件,除非它们正在取消选择项目。

这也可以通过基于CurrentSelection计数在SelectionChanged事件上设置SelectedItems (尚未实现)来完成,但这将触发SelectionChanged两次。 在我看来,我们应该有办法在任何东西到达 Core 之前主动控制选择行为。

今天玩了一下 CollectionView,我注意到 UWP 比 Android 和 iOS 落后很多,我不知道为什么。

只是想确认它是否计划在最终确定时提供完整的 UWP 支持?

除了上面提到的 ItemAppearing/Disappearing 事件之外,任何获得项目视图的方法的计划:
View GetView(object item)
如果项目没有具体化,我猜它应该返回 null。

ItemAppearing 怎么样? 我没有看到任何关于它的消息

我在玩CollectionView并面临行高不均匀的问题。 我看到最近引入了ItemSizingStrategy ,但它的行为仍然很奇怪。

我玩弄了DataTemplateGallery ,当切换到MeasureAllItems我得到以下结果(iPhone 6,iOS 12.1.4):

向右滑动并返回后,结果更改为:

@hartez这是否可以正常工作或仍在进行中(找不到任何问题)?

RemainingItemsThresholdReached 是否已实施?

它在 4.0.0.169046-pre5 中的 CollectionView 控件 XAML 上不可用。

谁能告诉我 RemainingItemsThresholdReached 是 4.0 版本的一部分吗? 如果是,请提供有关如何使用该功能的示例代码。

@Dresel如果你认为这是一个错误,你能开一张新票吗? 如果能被跟踪就更好了。

@melucas @chandrubk我不认为RemainingItemsThresholdReached正在处理中。

https://github.com/xamarin/Xamarin.Forms/branches/all

我也希望尽快实现此功能(以及刷新视图),因为没有它我无法触摸CollectionView

4323

我们需要像 ScrollView 那样的 Scrolled Event

问候,

4323

我们需要像 ScrollView 那样的 Scrolled Event

问候,

我支持这一点。
此外,当滚动停止/完成时获取和事件会很棒。

在IOS中,UICollectionview是UIScrollview的子类,所以我们可以从UIScrollViewDelegate得到scrollViewDidEndDecelerating UIScrollViewDelegate

在 Android 中,我认为我们可以扩展RecyclerView.OnScrollListener

这将为自定义刷新、视差、同步滚动元素等打开更高级和更完善的场景。

有没有可能为 Android 提供开箱即用的动画,例如 Recycler View 的动画?

有没有可能为 Android 提供开箱即用的动画,例如 Recycler View 的动画?

你指的是哪些动画? Android 渲染器基于 RecyclerView 构建,因此它已经使用默认动画来添加/删除项目。

你好,

我正在使用 4.0.0.304370-pre8。
使用 CarouselView 时,来自(下面的链接)的示例在 UWP 上不显示任何内容。
但 CollectionView 显示列表。 为 UWP 启用 CarouselView 是否需要任何特定配置?

https://devblogs.microsoft.com/xamarin/xamarin-forms-4-0-feature-preview-an-entirely-new-point-of-collectionview/

谢谢。

@noypi

虽然 CollectionView 在技术上可以在 UWP 上“工作”到相当小的程度,但 CollectionView 和 CarouselView 的完整实现从一开始就严格在 Android 和 iOS 上完成。 目前没有安排 UWP 的正式工作,但我们会不断收集反馈。 如果你想特别讨论你在 UWP 上所做的工作类型,你可以在 paul 给我发送电子邮件。 [email protected]

根据规范,TableView 会被 CollectionView 完全取代吗?

另一个问题:既然没有单元格了,如何为iOS添加一个dislorure指示器? 使用 ListView 可以通过自定义渲染器实现。

根据规范,TableView 会被 CollectionView 完全取代吗?

TableView 将仍然存在。 我们不会删除任何现有控件。

另一个问题:既然没有单元格了,如何为iOS添加一个dislorure指示器? 使用 ListView 可以通过自定义渲染器实现。

在 iOS 上,CollectionView 使用 UICollectionView 呈现,这意味着它的单元格是 UICollectionViewCells。 并且 UICollectionViewCells 没有附属视图(如披露指示符)。 因此,对于任何 UI 元素,例如披露指示符或复选标记,您都需要在 ItemTemplate 中创建这些元素。

如何禁用对某些类型的项目的选择? 我有多个数据模板,想禁用其中一些模板的选择。

@hartez将 ItemTemplate 设置为 DataTemplateSelector 时出现异常: System.InvalidOperationException: LoadTemplate should not be null

我认为模板将支持开箱即用

@hartez将 ItemTemplate 设置为 DataTemplateSelector 时出现异常: System.InvalidOperationException: LoadTemplate should not be null

我认为模板将支持开箱即用

他们应该是; 也许您遇到了错误。 请打开一个问题,以便我们进行调查。

@toomasz在打开问题之前,您能否将您的 Nuget 更新到最新的预发布(或每晚)并再次测试选择器? 当不支持DataTemplateSelector时,就会出现您所看到的问题。

@hartez目前是否正在对页眉和页脚以及刷新视图进行任何工作? 如果我能腾出时间,我可能会研究任何一个,但我想确保我没有踩到你的脚趾。

@adrianknight89它适用于 4.0! 惊人的

@hartez目前是否正在对页眉和页脚以及刷新视图进行任何工作? 如果我能腾出时间,我可能会研究任何一个,但我想确保我没有踩到你的脚趾。

目前什么都没有做——如果你想尝试一下,那就太好了。
提醒一下,经过今天的一些讨论,我们添加了两个与页眉和页脚相关的新属性 - IsHeaderStickyIsFooterSticky ,用于指定它们是随项目滚动还是保持原位。 如果您想与页眉/页脚一起解决这些问题,那会很棒,但如果我们让它们以一种或另一种方式工作并且以后可以实现这些属性,那也会很棒。

是否有计划支持 UWP 上的集合视图?

是的。 目前的实施有点落后于其他平台,但计划是全力支持它。 您可以在https://gist.github.com/hartez/7d0edd4182dbc7de65cebc6c67f72e14查看功能进度

有关 RefreshView 的任何信息?
我有最新的 Xamarin 4 测试版,但找不到 RefreshView 类型

有关 RefreshView 的任何信息?
我有最新的 Xamarin 4 测试版,但找不到 RefreshView 类型

RefreshView 尚未实现。 您可以在此处跟踪功能进度。

添加GroupItemsBinding ?

如何添加 GroupItemsBinding 属性来指定哪个属性包含组的子项? 这将允许嵌入子集合属性,而不是强制组从集合继承

好处:

  • 能够(反)序列化分组集合到/从 JSON。
    从集合中继承组会阻止 JSON(反)序列化(因为 JSON 数组仅支持一系列值而不支持属性)。 当应用程序进入后台或您的应用程序 API 向您发送视图模型时,需要(反)序列化视图模型以保留视图模型状态。 当前的解决方法是拥有第二个数据结构,并在每次数据更新时执行代价高昂的重复 + 转换。
  • 能够将您自己的基类用于组项目(例如ViewModelBase
  • 避免使用集合的所有继承属性污染组对象

例如,您可以从 docs.microsoft.com编写此
```C#
公共类 PageTypeGroup :列表
{
公共字符串标题{获取; 放; }
// 更多属性...
}

like this instead:

```C#
public class PageTypeGroup
{
    public string Title { get; set; }
    // More properties ...

    public List<PageModel> Children { get; set; }
}

使用 XAML:

C# <CollectionView GroupItemsBinding = "{Binding Children}" ...> </CollectionView>

不指定 GroupItemsBinding 将与现有实现兼容,相当于GroupItemsBinding="{Binding .}"

PS 我早在 2018 年 7 月就提交了这个提案。

2019 年 8 月 23 日更新:已实施分组,但没有此修复; 见组数据

我希望现在添加这个还为时不晚。

如何支持多个分组级别?
将允许显示树木

例如 Flutter 具有ExpansionTile示例

关于 CollectionView,我遇到了一个问题,我认为这是一个很好的添加功能。

在水平列表中,通过滚动,通常设计师会在屏幕中不完全可见的元素上添加“阴影”效果。 目前(据我所知)在 Xamarin.Forms 中无法做到这一点。 你不认为这将是一个有功能的 niec 吗? 例如,它可以像布尔值一样简单,它将“投影”应用于仅以 X 百分比可见的元素。

我提出了一个 Position 属性。 此属性将保存当前项目的索引。 这将允许轻松集成ViewPagerIndicator和类似的指标。

我知道确定“当前项目”可能很棘手。 如果启用了捕捉,则应该很容易确定视图被捕捉到哪个项目。 不捕捉正确的选择将取决于用例:也许它是占据视图起点或中点的项目。

作为 ScrollTo() 的替代方案,此属性还可以允许简单的双向访问。

@hartez我们原以为这会为 4.0 版本做好准备,但惊讶地发现它还没有完成。 如果没有滚动和刷新功能,我们就无法测试 CollectionView。 您能告诉我们在推出之前需要等待多少个 sprint 吗? 我们已决定不再随 ListView 一起发布任何内容,并希望此控件尽快可用。

@hartez我们需要一种方法让 CollectionView 具有列表布局来调整其项目内容的大小。 我认为这是一个常见的用例:
image
在此示例中,按钮应直接位于集合视图下方。 我认为当 VerticalOptions 是 Start 时它应该这样工作

当剩余物品阈值达到属性测试时

我对单个项目行为的 CollectionView 流程是否在屏幕大小更改时模仿 iOS 本机行为有疑问。 我给你举个例子:

iOS 中的图片库单元是使用 CollectionView 创建的,您可以定义一个单独的单元。 开箱即用的行为是,在单行中绘制的单元格数量是根据屏幕大小动态变化的。 在手机上我可能装 4 件物品,但在平板电脑上我可能装 8 件或 9 件。

Forms 版本也会提供这个吗? 到目前为止,我读过的示例我只看到了您设置 GridItemsLayout Span 属性的位置。 这导致了可以绘制多少项目的硬编码值,并且在各种屏幕尺寸的世界中,硬编码实际上在 2014 年似乎如此。:-P

UWP 有四种选择模式状态
{
没有任何,
单身的
多种的,
延长,
}
image

image

我觉得 Android 和 IOS 中的 Four state 也很有用
只需看看文件资源管理器
image

有没有简单的填充属性的计划? #6605 对于我的特定用例,我可能会使用适当大小的空白页眉和页脚(一旦开发了这些功能),但这会有点麻烦,不适合所有四个边都可以填充的网格布局需要。

在集合视图中重新排列列表项的任何计划。

规范是否涵盖了如何禁用 CollectionView 中特定项目的选择?

// Any possible API could be helpful
private void OnSelectionChanging(object sender, SelectionChangingEventArgs e)
{
  if (...)
      e.Cancel = true;
 }

目前我解决了它,但这不会阻止应用 Selected VisualState。

void OnCollectionViewSelectionChanged(object sender, SelectionChangedEventArgs e)
{
    // Deselect the item.
    if (sender is CollectionView cv && e.CurrentSelection...)
    {
        cv.SelectedItem = null;
    }
}

垂直滚动条颜色和水平滚动条颜色会很棒!

滚动的方向怎么样,我的意思是从右向左滚动,而不是内容本身

我想要分隔符...

有可能“记住”并应用滚动位置会很棒。

令人惊奇的是,可以为每秒或 X 个项目使用不同的项目模板。 这将使得可以为每第二个项目和许多其他样式可能性创建灰色背景。

你不能用模板选择器做到这一点吗? 使用位置
模运算符?

在星期二,2019年8月13日,16时53分Legacyorder [email protected]写道:

什么会如此惊人,将有可能使用不同的项目
每秒或 X 项的模板。 这将使创建
每隔一个项目和许多其他样式的灰色背景
可能性。


您收到此消息是因为您订阅了此线程。
直接回复本邮件,在GitHub上查看
https://github.com/xamarin/Xamarin.Forms/issues/3172?email_source=notifications&email_token=AC4YCKDFCH3WFENRCLPWEC3QELDE3A5CNFSM4FHJRXPKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63KLDNX8520000000000000000001001010010052000000200100010 ;
或静音线程
https://github.com/notifications/unsubscribe-auth/AC4YCKHXX5YSR7M3S4VU5QLQELDE3ANCNFSM4FHJRXPA
.

圆形滚动应该不错。 我想这很容易实现。

我想要一个“AbsoluteItemsLayout”作为 CollectionView 的 ItemsLayout 以便可以在列表中设置绝对位置,目前我看不到其他解决方案,而是在后面的代码中进行。

在使用 GridItemsLayout 时,是否可以允许项目跨越多行或多列? 这绝对是一个值得拥有的功能。

你们也可以将 Scrolled 事件暴露给这个控件吗? 这样做的目的是当我到达列表底部时,我想重新加载其他项目。 我不知道 CollectionView 是否检测到它是否在 ScrollView 内部并禁用滚动功能。

你们也可以将 Scrolled 事件暴露给这个控件吗? 这样做的目的是当我到达列表底部时,我想重新加载其他项目。 我不知道 CollectionView 是否检测到它是否在 ScrollView 内部并禁用滚动功能。

你的愿望实现了! 检查版本 4.2 :)
https://docs.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/collectionview/scrolling

您不应在 ScrollView 中包含 CollectionView,否则虚拟化将不起作用。

你们也可以将 Scrolled 事件暴露给这个控件吗? 这样做的目的是当我到达列表底部时,我想重新加载其他项目。 我不知道 CollectionView 是否检测到它是否在 ScrollView 内部并禁用滚动功能。

你的愿望实现了! 检查版本 4.2 :)
https://docs.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/collectionview/scrolling

您不应在 ScrollView 中包含 CollectionView,否则虚拟化将不起作用。

我在 4.2.0.709249
我错过了什么吗?
image

image

我确实有 4.2.0.709249 的 Scrolled 事件。
尝试删除 bin/obj 文件夹并检查 NuGet 合并以确保。

我们很快会在 Android 和 iOS 4.2 中获得 RTL 支持吗?

我们很快会在 Android 和 iOS 4.2 中获得 RTL 支持吗?

一些支持已经存在; FlowDirection 支持应该已经在 CollectionView 项目中工作了。 仍然不完整的是水平 CollectionView 布局的滚动方向。 滚动方向应与 Android 上的 FlowDirection 匹配,但对于其他平台,我们仍有一些工作要做; 这项工作的目标是在 4.3 中完成。

如果您在使用 FlowDirection 和 CollectionView 时遇到任何错误,请打开一个问题,我们会查看。

你能描述一下 RTL 支持没有做什么吗?
因为在规范中,它甚至没有标记为进行中或完成。

2019 年 9 月 5 日星期四上午 2:19,EZ Hart, [email protected]写道:

我们很快会在 Android 和 iOS 4.2 中获得 RTL 支持吗?

一些支持已经存在; FlowDirection 支持应该已经是
在 CollectionView 项目中工作。 还没有完成的是卷轴
水平 CollectionView 布局的方向。 滚动方向
应该与 Android 上的 FlowDirection 匹配,但我们还有一些工作要做
为其他平台做那个。

如果您在使用 FlowDirection 和 CollectionView 时遇到任何错误,
请打开一个问题,我们来看看。


您收到此消息是因为您发表了评论。
直接回复本邮件,在GitHub上查看
https://github.com/xamarin/Xamarin.Forms/issues/3172?email_source=notifications&email_token=ACDWB3GSYAQSADERHWVTJX3QIANMNA5CNFSM4FHJRXPKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LODMX55000000,VMVBW63L0DMX550000000000000000000000001
或静音线程
https://github.com/notifications/unsubscribe-auth/ACDWB3HMFCHBRZWD5AJMXH3QIANMNANCNFSM4FHJRXPA
.

未完成:水平布局的滚动方向。

如果您在水平滚动的 CollectionView 上设置 FlowDirection = RightToLeft,则现在在 iOS 和 UWP 上滚动方向不会是从右到左(我相信它_确实_适用于 Android)。

一些 LoadingDataTemplate 怎么样?

根据我将数据异步加载到 ListView/CollectionView 的经验,在填充 listview/collectionview 之前,有时可能会有空白空间。

添加 LoadingDataTemplate 可以在填充大量数据并且页面已经出现时提供额外的响应能力。

我认为加载指示器有两种使用方式。 一种是最初显示CollectionView 。 将显示多个占位符单元格,直到将数据添加到ItemsSource集合中。 第二个是在列表底部添加更多数据时。 对于第二个,我认为我们可以利用页脚?

第一个需要更多的工作(例如,最初使用 3-5 个具有相同占位符数据模板的项目加载源,然后删除这些项目并在获取时添加实际数据)。 另一种方法是将骨架视图放在CollectionView之上,并在数据准备好时将其隐藏。 我目前使用ListView遵循这种方法。

我还没有尝试过,但我们可以先将EmptyView设置为加载视图,如果没有结果,请更改EmptyView的模板以显示“未找到”消息。

@adrianknight89

另一种方法是将骨架视图放在CollectionView之上,并在数据准备好时将其隐藏。 我目前使用ListView遵循这种方法。

这听起来与我遵循的方法相同,即在上面放置一些活动指示器。 将 ListView 设置为 IsVisible = false 和 ActivityIndi​​cator IsVisible = true,然后在填充列表视图后反转这两个值。

@adrianknight89

我还没有尝试过,但我们可以先将 EmptyView 设置为加载视图,如果没有结果,请更改 EmptyView 的模板以显示“未找到”消息。

有个主意! 虽然这可能会奏效,但我确实觉得在 CollectionView 上有关于 LoadingDataTemplate 和 EmptyView 的单独模板属性会更好地简化。

我同意最好有两个不同的属性。 除了简单性之外,将一个属性用于两个不同的目的并没有多大意义。 也许EmptyView应该被命名为BackgroundView这样我们就可以将它用于任何目的。 (编辑: BackgroundView是完全不同的东西。)

@LeoJHarris我添加了 #7447 以获得BackgroundView支持。 我们可以使用EmptyViewBackgroundView来支持上述两种场景,虽然这还不是你想要的 100%,但它应该比使用EmptyView来支持两者更好场景。 您可以使用BackgroundView作为加载屏幕,并在数据准备好后将其归零。

@adrianknight89如果 CollectionView 在数据准备好后处理'null it out'而不是手动控制它会很棒(除非你已经暗示了这一点)。

当快速滚动使用 CollectionView 的 RemainingItemsThreshold 的页面时,我们遇到了两个不同的问题。

  1. 应用程序冻结,必须强制退出
  2. CollectionView 中的项目堆叠在一起(参见图片

一直找不到其他人有这个问题。 你看到报道了吗?

@Bronson15你如何处理RemainingItemsThresholdReached事件? 快速滚动会多次触发它,因此您需要在等待更新数据源时忽略事件调用,否则它们会堆积起来。 此外,尝试在主线程上更新您的 UI。

如果您仍然遇到问题,您可以打开一个带有重现的新问题以进行调查。

@Bronson15这两个问题。
尝试使用 ObservableRangeCollection 并修复 #2。
仍然存在冻结/空白列表问题:在模拟器上运行时,我看到 cpu 峰值,似乎是一个无限循环。

编辑:仅在 iOS 上中断,在 Android 上工作正常。

大家好,
即使我尝试使用 RemainingItemsThreshold 和 RemainingItemsThresholdReachedCommand 并注意到分配给 RemainingItemsThresholdReachedCommand 的函数会被多次调用(第一次调用两次,下次调用 4 次等),即使我没有快速滚动。 我还可以使用新的 Xamarin Forms 项目 (v.4.2.0.778463) 重现它。
你能尝试在你的最后重现它吗? 这是下面的简单代码片段:

XAML:

<CollectionView
        x:Name="StackLayout"
        ItemsSource="{Binding LatestStories}"
        RemainingItemsThreshold="10"
        RemainingItemsThresholdReachedCommand="{Binding RemainingStoriesCommand}">
        <CollectionView.ItemTemplate>
            <DataTemplate>
            <Grid
                                ColumnSpacing="16"
                                HeightRequest="110"
                                RowSpacing="0">

                    <Grid.RowDefinitions>
                        <RowDefinition Height="*" />
                        <RowDefinition Height="Auto" />
                        <RowDefinition Height="Auto" />
                    </Grid.RowDefinitions>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto" />
                        <ColumnDefinition Width="*">
                        </ColumnDefinition>
                        <ColumnDefinition Width="Auto" />
                    </Grid.ColumnDefinitions>

                    <!--  Blog title  -->
                    <Label
                                    Grid.Column="1"
                                    Margin="0,8"
                                    FontSize="14"
                                    LineBreakMode="TailTruncation"
                                    LineHeight="{OnPlatform Default=-1,
                                                            Android=1.25,
                                                            iOS=1.25}"
                                    MaxLines="2"
                                    Text="{Binding Title}" />

                    <!--  Author name  -->
                    <Label
                                    Grid.Row="1"
                                    Grid.Column="1"
                                    Margin="0,8,0,0"
                                    FontSize="12"
                                    LineHeight="{OnPlatform Default=-1,
                                                            Android=1.5}"
                                    Text="{Binding Author}" />

                </Grid>
            </DataTemplate>
        </CollectionView.ItemTemplate>
</CollectionView>

查看型号:

public class ArticleListViewModel
    {
        public ObservableRangeCollection<FeedItem> LatestStories { get; } = new ObservableRangeCollection<FeedItem>();
        public Command RemainingStoriesCommand => new Command(() => RemainingStories());

        public ArticleListViewModel()
        {
            RemainingStories();
        }

        private async void RemainingStories()
        {
            var feeds = await GetRemoteFeedsAsync();
            try
            {
                Device.BeginInvokeOnMainThread(() =>
                {
                    LatestStories.AddRange(feeds);
                });

            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex, "");
            }
        }

        private async Task<List<FeedItem>> GetRemoteFeedsAsync()
        {
            try
            {
                Stopwatch watch = new Stopwatch();
                watch.Start();
                var allItems = new List<FeedItem>();
                HttpResponseMessage response;
                var httpClient = new HttpClient();
                response = await httpClient.GetAsync("https://jsonplaceholder.typicode.com/photos").ConfigureAwait(false);
                if (response.IsSuccessStatusCode)
                {
                    var data = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
                    var testData = JsonConvert.DeserializeObject<List<TestJson>>(data);
                    if (LatestStories.Count == 0)
                    {
                        testData = testData.Take(20).ToList();
                    }
                    else
                    {
                        testData = testData.Skip(LatestStories.Count).Take(20).ToList();
                    }

                    foreach (var item in testData)
                    {
                        var newItem = new FeedItem
                        {
                            Title = item.id.ToString(),
                            Description = item.title,
                            ImagePath = item.thumbnailUrl,
                            Link = item.url,
                            PublishDate = "2019-09-11",
                            Category = ""
                        };
                        allItems.Add(newItem);
                    }
                }
                watch.Stop();
                Debug.WriteLine("TPL Total Time: " + watch.ElapsedMilliseconds);
                return allItems;
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex, "");
                throw;
            }

        }
    }

@Bronson15 @andreabalducci @techduggu由于在处理RemainingItemsThresholdReachedCommand时我们不会阻止 UI,因此由于滚动模式而多次点击命令是正常的。 请查看我如何使用锁定机制处理问题: https :

其他方法是在远程获取正在进行时启用/禁用您的命令或取消订阅/订阅事件。 根据我的经验,使用信号量效果最好,因为有时在您尝试启用/禁用或取消订阅/订阅回调时会触发多个调用。

@hartez @samhouts @davidortinau我认为这个问题将来会经常出现。 上面的建议是否应该成为剩余项目文档的一部分? 我会让文档团队创建一个用于测试的远程提要,并推荐一个编码模式以供参考,这样人们就不会一直寻求帮助。

@techduggu您的代码存在不同的(次要)问题。 我会在 Stack Exchange 上对其代码进行审查。 这不是现在的地方。

@adrianknight89感谢您突出显示“由于您的滚动模式”一词。 这引发了我想了解更多信息的渴望。 在阅读了 RecyclerView 的官方文档和其他一些资源后,是的,我可以确认由于滚动模式,它被多次调用,这些模式是 SCROLL_STATE_IDLE、SCROLL_STATE_DRAGGING 或 SCROLL_STATE_SETTLING,具体取决于我们的滚动状态。
https://developer.android.com/reference/android/support/v7/widget/RecyclerView.OnScrollListener

您的代码和此 android 指南(https://github.com/codepath/android_guides/wiki/Endless-Scrolling-with-AdapterViews-and-RecyclerView)也证实了我们应该通过锁定或使用来处理无限滚动上述滚动状态(主要需要自定义渲染器)。 因此,使用 Xamarin.Forms,我已经尝试了您的代码,并且它的工作非常有魅力。 :) 我会推荐并支持你的意见,将这个建议作为文档的一部分,以避免像我这样的人(知识不足)提出这样的问题。 :)

此外,注册。 您在上面的代码片段中提到的小问题 - 这只是一个用于测试集合视图无限加载的 POC 项目,但是如果您注意到除了愚蠢的空检查等之外的任何内容,我很想知道您的输入。

谢谢!

@adrianknight89啊,是的。 我们的 Busy 支票丢失了,这有助于解决堆叠问题。

我还按照您的建议实施了信号量,它似乎缓解了一个问题,即在向 ItemsSource 添加新项目时,视图会将滚动位置重置为开头。 奇怪的是,在尝试中添加调用; 最后; 就像你在测试文件中所做的那样,把这个问题带回来了。

滚动到列表末尾时仍然存在冻结问题。 视图变为空白,应用程序冻结。

编辑:滚动位置重置仍然存在,但不那么频繁。 加载更多项目的渲染在设备上也非常不稳定。

@techduggu我没有 VS,但只是看代码,你应该等待RemainingStories() ,将远程调用移到 try 中,并使用HttpClient使用(理想情况下使用应用程序中的单个静态实例并且永远不会处理它),但我会在这里停止。 :)

@Bronson15 CollectionView 存在重置滚动位置并导致 UI 冻结的问题。 我认为它已通过 #7285 修复,但这仅限于 iOS。 你能测试最新的每晚 Nuget 看看你是否还有问题吗? 每晚提要 URL 位于表单的 GitHub 主页上。 如果问题仍然存在,请打开一个带有复制代码的问题,以便我们查看。

@adrianknight89滚动浏览每晚构建。 似乎问题已基本解决(我确实看到它发生过一次)。 现在似乎列表只是在无限循环中,而不是结束。 AFAIK 规范中没有任何属性可以阻止这种情况发生?

@Bronson15不应该发生无休止的循环。 你是在 iOS 还是 Android 上看到的? 当您到达远程提要的末尾时,您需要结束循环(即立即从RemainingItemsThresholdReachedCommand返回而不发出另一个数据库调用)。

一旦视图滚动停止,则不应再触发该命令。 我使用返回延续令牌的 Azure Cosmos。 当令牌为空时,我知道没有更多内容要加载,因此我的RemainingItemsThresholdReachedCommand基于该令牌工作。 你应该实现类似的东西。

@adrianknight89啊。 有趣的。 添加了对结果计数的检查,如果为 0 则返回。修复了无限滚动。 感谢您的帮助!

@adrianknight89对 iOS 崩溃问题进行了
1000 个项目在 Android 上几乎是实时的,在 iOS 上必须等待 5-7 秒才能呈现视图。 调试、iPhone Xs 和红米 Note 7

@andreabalducci你在 XS 模拟器上吗? 物理设备上的行为如何? 如果视图渲染缓慢,这可能是 iOS 的另一个需要调查的问题。 再次,很高兴看到复制品。

@adrianknight89 @andreabalducci是的,我的 Xs Max 需要大约 1-5 秒才能加载更多项目。 该视图将清空并重新加载所有项目,而不是将项目添加到已呈现的列表中。

@adrianknight89两个物理设备,iOS 模拟器都有同样的问题。

在 iOS 超过 20 秒之前,我们从数据模板中删除了所有堆栈布局,并在切换到 FormattedString 时获得了一些速度,启用了编译绑定。

在 iOS 上,当添加 ObservableRangeCollection(来自 mvvm 助手)时,视图会变黑并重绘,在 Android 上工作正常。

这对我来说听起来像是一个单独的问题。 我认为这与其余项目无关。

在使用 GridItemsLayout 时,是否可以允许项目跨越多行或多列? 这绝对是一个值得拥有的功能。

有这方面的信息吗?

@LynoDesu正在为此跟踪一个问题: https :

@LynoDesu正在为此跟踪一个问题:#6357

啊,太好了! 谢谢。 如果我想为此做出贡献,我从哪里开始?

阅读主页 wiki 以及Contributing.md

@adrianknight89发现了空白 + 返回开始问题,在此处重现https://github.com/andreabalducci/XamarinCollectionView/blob/b186e563ff8391dfb473e62e5a4c4587e8d4e9da/cvrepro/cvrepro/ListViewModel.cs#L46

如果集合在按预期绑定所有工作之前有任何项目,则从空集合开始会触发该问题。

在 iPhone 模拟器上测试。

我看到了这个问题。 这可能与#7548 相同。 您可能想在那里发布您的复制品。

使用 IsGrouped 时,Android 上的 CollectionView 似乎被窃听。

CollectionView.GroupHeaderTemplate根本没有呈现。 在 iOS 上它工作正常。 您可以使用 Microsoft 站点中的分组示例来测试它。

    public class AnimalGroup : List<Animal>
    {
        public string Name { get; private set; }

        public AnimalGroup(string name, List<Animal> animals) : base(animals)
        {
            Name = name;
        }
    }

    public class Animal
    {
        public string Name { get; set; }
        public string Location { get; set; }
        public string Details { get; set; }
        public string ImageUrl { get; set; }
    }

    public List<AnimalGroup> Animals { get; private set; } = new List<AnimalGroup>();

    Animals.Add(new AnimalGroup("Bears", new List<Animal>
        {
            new Animal
            {
                Name = "American Black Bear",
                Location = "North America",
                Details = "Details about the bear go here.",
                ImageUrl = "https://upload.wikimedia.org/wikipedia/commons/0/08/01_Schwarzbär.jpg"
            },
            new Animal
            {
                Name = "Asian Black Bear",
                Location = "Asia",
                Details = "Details about the bear go here.",
                ImageUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/b/b7/Ursus_thibetanus_3_%28Wroclaw_zoo%29.JPG/180px-Ursus_thibetanus_3_%28Wroclaw_zoo%29.JPG"
            },
        }));
<CollectionView ItemsSource="{Binding Animals}"
                        IsGrouped="true">
            <CollectionView.GroupHeaderTemplate>
                <DataTemplate>
                    <Label Text="Header"
                           BackgroundColor="LightGray"
                           FontSize="Large"
                           FontAttributes="Bold" />
                </DataTemplate>
            </CollectionView.GroupHeaderTemplate>
            <CollectionView.ItemTemplate>
                <DataTemplate>
                    <Grid Padding="10">
                        <Image Grid.RowSpan="2"
                               Source="{Binding ImageUrl}"
                               Aspect="AspectFill"
                               HeightRequest="60"
                               WidthRequest="60" />
                        <Label Grid.Column="1"
                               Text="{Binding Name}"
                               FontAttributes="Bold" />
                        <Label Grid.Row="1"
                               Grid.Column="1"
                               Text="Child"
                               FontAttributes="Italic"
                               VerticalOptions="End" />
                    </Grid>
                </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>

https://docs.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/collectionview/grouping

重要的

目前仅在 iOS 上支持使用 CollectionView 对数据进行分组。

哎呀,我错过了那部分。 谢谢。

对于我们这些想要在 iOS 和 Android 上都显示分组列表但又不想使用 ListView 的人来说,现在还有什么可以像 CollectionView 一样灵活的吗? 还是我们被 ListView 困住了?

我希望这是问的正确地方。 我在最初发布的规范中看到IsHeaderStickyIsFooterSticky属性,但我在讨论或实现的源代码中没有看到任何进一步提及它们。 这些是否仍在此视图的路线图上?

在 collectionview 中,我们需要 ItemAppeared、ITemDisappeared。
有什么办法可以实现吗?

@IosDeveloperHarsh Scrolled事件在事件参数中提供了很多有用的信息。 在那里查看第一个和最后一个可见项目索引。

@rafiwardak2003带有 CollectionView 组的 Gallery 示例从今天起可在 Android 上运行,尽管我还没有运行您提供的示例。 你用的是哪个Nuget? 尝试使用最新的预发布版本或每晚版本。

@cabal95我没有资格回答这个问题,但如果我不得不猜测它们最终会被实施。 也许,我们需要有一个活跃的问题来跟踪这个。 我知道最初的页眉/页脚工作排除了粘性内容。

我认为应该删除 SelectionChangedCommandParameter ,而是将所选项目自动设置为参数。

如果可能的话,使用这样的属性会很好

public ICommand => new Command<MySelectedItemModel>((item) => {}

但这也应该没问题:

public ICommand => new Command<object>((item) =>{ var selectedItem = item as MySelectedItemModel;}

我认为应该删除 SelectionChangedCommandParameter ,而是将所选项目自动设置为参数。

如果可能的话,使用这样的属性会很好

public ICommand => new Command<MySelectedItemModel>((item) => {}

但这也应该没问题:

public ICommand => new Command<object>((item) =>{ var selectedItem = item as MySelectedItemModel;}

如果用户想使用 SelectedItem 以外的其他东西作为他们命令的参数怎么办?

我认为应该删除 SelectionChangedCommandParameter ,而是将所选项目自动设置为参数。
如果可能的话,使用这样的属性会很好
public ICommand => new Command<MySelectedItemModel>((item) => {}
但这也应该没问题:
public ICommand => new Command<object>((item) =>{ var selectedItem = item as MySelectedItemModel;}

如果用户想使用 SelectedItem 以外的其他东西作为他们命令的参数怎么办?

您说得有道理,但我很难看到它的用例,因为您是在 CollectionView 级别设置参数。 我希望它是我第一次使用它时选择的项目。 但是您也许可以将所选项目设置为默认值? 如果您使用该事件,您将获得,所以我认为许多开发人员也期望它用于命令。

我还想请求一个功能,这个 CollectionView 不会在整个屏幕上伸展,只是使用高度取决于项目的数量。

我正在尝试查看多个列表
IE
采购

扣除额

全部的
全部的

但是项目 1 和 2(一个 CollectionView)只是占据了太多的高度,即使我只有 3 或 4 个项目并且在我看到扣除部分之前有一个 BIIIIIIIIIIIIIIIG 差距

我最终基于 StackLayout 制作了自己的 ItemsCollection 控件

我还想请求一个功能,这个 CollectionView 不会在整个屏幕上伸展,只是使用高度取决于项目的数量。
我最终基于 StackLayout 制作了自己的 ItemsCollection 控件

我认为您正在寻找的可能是Bindable Layouts

我还想请求一个功能,这个 CollectionView 不会在整个屏幕上伸展,只是使用高度取决于项目的数量。
我最终基于 StackLayout 制作了自己的 ItemsCollection 控件

我认为您正在寻找的可能是Bindable Layouts

嘿! 正是我需要的。 从什么时候开始 BindableLayouts 存在?

感谢大家对这个问题的讨论! 如果您有任何其他功能请求或错误报告,请为每个问题打开新问题。 我们现在正在关闭这个问题。

此页面是否有帮助?
0 / 5 - 0 等级