0

我正在尝试在 WinUI/UWP 应用程序中实现类似于 Notion 或 Craft 的文档编辑器。这些应用程序没有使用“单字段”编辑器(如 MS Word 那样),而是显示垂直堆栈的内容行(所谓的“块”),其中可以包含文本、媒体、链接预览、LaTeX 等。这些行可以用::侧面的把手重新排列:

Notion UI 录制

所以我一直在寻找一些列表/堆栈控件:

  • 回收不可见的行视图(即 XAML 术语中的“虚拟化”)。
  • 允许通过拖放(单个或多个)对行重新排序。
  • 根据内容的高度增长或缩小自动调整行高(由于用户的输入或因为应用程序的窗口水平调整大小并包装了一些内容)。

我不需要的功能标题、列、排序、过滤。我已经查看了 WinUI 2.x 和 Windows Community Toolkit 中的以下控件,但看起来它们中的每一个都缺少一个或多个所需的功能。

列表显示

它似乎是拖放列表的首选控件,但它不能动态调整项目的大小。此外,它的拖动使用了整个项目区域,而我需要使其仅::在侧面有一个手柄时可用。

ItemsStackPanel

StackPanel的虚拟化支持版本,但据我了解,面板应该用于子项的简单布局,而不是用于基于数据源呈现长列表。

VariableSizedWrapGrid

这是唯一一个官方声明支持可变大小项的列表/网格控件,但同时不支持虚拟化。但是,我从 2013 年找到了一个基于预先计算不可见元素的内容大小的解决方案。

物品中继器

一个非常基本的控件,它本身不提供虚拟化:“ItemsRepeater 在连接到支持虚拟化的主机时支持虚拟化。”

数据网格

WCT 的一个相当繁重的控制似乎是唯一一个根据其内容动态调整单元格大小的控制。不幸的是,它不允许行重新排序(仅排序),所以我也不能使用它。


我错过了什么?如果没有,我想知道哪一个是最好的基础。谢谢!

4

2 回答 2

1

我不得不说没有任何控制可以满足所有的要求。其实::是用来控制 darg 指定项的,你可以在 ListView 控件中实现类似的行为。

ListView 允许您通过将CanReorderItemsandAllowDrop属性设置为True来轻松地对 ListView 中的项目重新排序。如果您不想让用户拖动特定项目,您可以将CanDragItems属性设置为TrueDragItemsStarting ,并为事件添加事件处理程序. 对于事件处理程序,您可以检查任何条件,然后如果要取消拖动操作,只需将事件参数的 Cancel 属性设置为 true。如下:

Xml代码:

<ListView x:Name="TargetListView"              
                CanReorderItems="True" CanDragItems="True" AllowDrop="True"         DragItemsStarting="TargetListView_DragItemsStarting">

            <ListViewItem>
                <TextBlock x:Name="item1" Text="item1"/>
            </ListViewItem>
            <ListViewItem >
                <TextBlock x:Name="item2" Text="item2"/>
            </ListViewItem>
            <ListViewItem>
                <TextBlock x:Name="item3" Text="item3"/>
            </ListViewItem>
          
  </ListView>

后面的代码:

private void TargetListView_DragItemsStarting(object sender, DragItemsStartingEventArgs e)
        {
            e.Cancel = e.Items.Any(o =>
            {
                if (o is TextBlock t && t.Name.ToString() == "item2")
                    return true;

                return false;
            });
        }

可以看到,ListView中有3个textBlock,名为item2的textblock的拖拽动作会受到限制。

于 2021-06-30T06:55:18.783 回答
0

事实证明,aListView 可以动态调整其项目的大小——只需将 aStackPanel放入 a 中,ListViewItem因为堆栈会向外“推”其父项的大小。正如这个答案所说:

容器控件喜欢GridRelativePanel自动缩放到其父元素的完整可用大小,而其他容器控件则喜欢StackPanel仅增长到其子元素所需的最小大小。

此外,在 aTextBox内添加 aListViewItem会使用文本输入行为覆盖拖动行为,但列表项仍可拖动到文本框外。我可以这样保留它,或者按照Arya 的回答将可拖动区域减少到::手柄。

于 2021-07-05T00:06:18.727 回答