mirror of
https://github.com/AtomUI/AtomUI.git
synced 2026-10-19 06:58:57 +08:00
12 KiB
12 KiB
Transfer 穿梭框
概述
穿梭框(Transfer)用于在两栏之间移动元素,完成选择行为。左侧为「源数据」面板,右侧为「目标数据」面板,用户通过勾选和穿梭按钮将数据在两栏间转移。适用于有大量选项需要筛选和整理的场景。
AtomUI 的 Transfer 控件复刻了 Ant Design 5.0 Transfer 的设计规范,在 .NET / Avalonia 平台上提供与 Ant Design React 版一致的视觉体验和交互行为。
设计原理
Ant Design 的 Transfer 设计哲学
Ant Design 对 Transfer 的定位是:「双栏穿梭选择框,在两栏之间移动元素,完成选择行为」。Transfer 的核心价值在于为用户提供直观的双栏对比操作界面——左侧展示可选数据,右侧展示已选数据,通过穿梭按钮在两栏间转移。
关键设计决策:
| 特性 | 设计意图 |
|---|---|
| 双栏布局 | 左源右目标的标准布局,清晰展示数据流向 |
| 全选/反选操作 | 支持批量操作,提高大量数据场景下的效率 |
| 搜索过滤 | 内置搜索框,在大量数据中快速定位目标项 |
| 自定义项渲染 | 通过 ItemTemplate 自定义列表项展示方式 |
| 单向模式 | IsOneWay 模式下仅支持从源到目标的单向转移,目标面板直接删除 |
| 分页支持 | 大量数据时启用分页,提高性能和可操作性 |
| 树形穿梭 | TreeTransfer 支持树形结构数据的穿梭操作 |
| 尺寸自适应 | 支持 Large/Middle/Small 三种尺寸 |
| 状态反馈 | 支持 Error/Warning 边框状态,配合表单验证使用 |
AtomUI 的实现架构
AtomUI Transfer 采用抽象基类 + 具体实现的分层架构,支持列表和树两种数据展示模式:
| 组成部分 | 说明 |
|---|---|
| AbstractTransfer | 抽象基类,定义穿梭框的通用属性、事件和穿梭逻辑 |
| ListTransfer | 列表穿梭框,源和目标面板均为列表视图 |
| TreeTransfer | 树形穿梭框,源面板为树视图,目标面板为列表视图 |
| TransferItemDecorator | 面板装饰器(内部),负责头部信息栏、搜索框、全选控件、页脚的布局 |
| TransferListView | 列表视图实现(内部),实现 ITransferView |
| TransferTreeView | 树视图实现,实现 ITransferTreeView |
| TransferSelectDropdown | 选择操作下拉菜单(内部),提供全选/反选/删除等批量操作 |
| ITransferView | 视图接口,定义穿梭视图的通用能力 |
| ITransferTreeView | 树视图接口,扩展 ITransferView,增加遮罩项支持 |
核心机制:
- 数据流基于
ItemsSource(全量数据)和TargetKeys(目标键集合)驱动,通过键集合的增减完成穿梭操作 - 源面板展示
ItemsSource - TargetKeys,目标面板展示ItemsSource ∩ TargetKeys - 搜索过滤通过
IValueFilter接口实现,支持自定义过滤逻辑 - 树形穿梭框的源面板使用遮罩机制(
SetMaskedItems)隐藏已转移的节点 - 穿梭按钮的启用/禁用状态由面板选中状态驱动
功能详解
列表穿梭(ListTransfer)
最常用的穿梭模式,源和目标面板均为扁平列表:
- 支持多选后批量穿梭
- 支持全选/反选操作
- 支持搜索过滤
- 支持分页(
PageSize > 0) - 支持自定义
SourceView和TargetView
树形穿梭(TreeTransfer)
用于树形结构数据的穿梭,源面板展示为树视图,目标面板为扁平列表:
- 源面板展示完整树结构,选中的节点在穿梭后被遮罩(灰显)
- 目标面板展示扁平化的已选项列表
- 支持默认展开所有节点(
IsDefaultExpandAll) - 支持自定义源面板树视图
单向模式
IsOneWay=True 时:
- 隐藏"转移到源"按钮
- 目标面板不再显示选择框(改为删除按钮)
- 用户只能从源穿梭到目标,在目标面板通过删除操作移回
搜索过滤
IsFilterEnabled=True 时在面板头部下方显示搜索框:
- 内置
Contains过滤器,也可通过Filter属性自定义 FilterValueSelector委托指定从数据项中提取过滤值的方式FilterPlaceholderText设置搜索框占位文本- 源/目标面板独立过滤
分页
PageSize > 0 时启用分页(仅 ListTransfer 支持):
- 面板底部显示分页控件
- 列表宽度自动扩大(使用
ListWidthLGToken) - 选择操作下拉菜单增加"选择当页"/"反选当页"/"删除当页"选项
自定义面板视图
通过 SourceView / TargetView 属性可以替换面板的内部视图实现:
<atom:TreeTransfer>
<atom:TreeTransfer.SourceView>
<atom:TransferTreeView IsDefaultExpandAll="True" />
</atom:TreeTransfer.SourceView>
</atom:TreeTransfer>
自定义页脚
通过 SourceViewFooter / TargetViewFooter 属性可以在面板底部添加自定义内容:
<atom:ListTransfer>
<atom:ListTransfer.SourceViewFooter>
<atom:Button SizeType="Small">Reload</atom:Button>
</atom:ListTransfer.SourceViewFooter>
</atom:ListTransfer>
本地化
Transfer 的操作文本通过本地化系统管理:
| 资源键 | 中文 | 英文 |
|---|---|---|
Item |
项 | item |
Items |
项 | items |
SelectAll |
全选所有 | select all data |
DeSelectAll |
取消全选 | deselect all data |
RemoveCurrentPage |
删除当页 | remove current page |
RemoveAll |
删除所有 | remove all data |
InvertSelectCurrentPage |
反选当页 | invert current page |
SelectCurrentPage |
选择当页 | select current page |
与 Ant Design 规范的对齐程度
| 特性 | Ant Design (React) | AtomUI (Avalonia) | 对齐情况 |
|---|---|---|---|
| 基本穿梭 | ✅ 双栏穿梭 | ✅ ListTransfer |
✅ 完全对齐 |
搜索过滤 showSearch |
✅ 内置搜索 | ✅ IsFilterEnabled |
✅ 完全对齐 |
单向模式 oneWay |
✅ 单向穿梭 | ✅ IsOneWay |
✅ 完全对齐 |
分页 pagination |
✅ 分页支持 | ✅ PageSize |
✅ 完全对齐 |
| 树形穿梭 | ✅ TreeTransfer | ✅ TreeTransfer |
✅ 完全对齐 |
自定义渲染 render |
✅ 自定义项渲染 | ✅ ItemTemplate |
✅ 完全对齐 |
自定义页脚 footer |
✅ 页脚插槽 | ✅ SourceViewFooter / TargetViewFooter |
✅ 完全对齐 |
标题 titles |
✅ 面板标题 | ✅ SourceTitle / TargetTitle |
✅ 完全对齐 |
自定义按钮文本 operations |
✅ 按钮文字 | ✅ ToSourceButtonText / ToTargetButtonText |
✅ 完全对齐 |
受控 targetKeys |
✅ 受控属性 | ✅ TargetKeys 绑定 |
✅ 完全对齐 |
受控 selectedKeys |
✅ 受控属性 | ✅ SelectedKeys 绑定 |
✅ 完全对齐 |
禁用 disabled |
✅ 禁用态 | ✅ IsEnabled |
✅ 完全对齐 |
状态 status |
✅ error/warning | ✅ Status 枚举 |
✅ 完全对齐 |
| 表格穿梭 | ✅ Table Transfer | ⚠️ 注释中有 DataGrid 方案 | ⚠️ 开发中 |
列表宽高 listStyle |
✅ 样式对象 | ✅ ListWidth / ListHeight |
✅ 完全对齐 |
onChange 回调 |
✅ 回调函数 | ✅ SelectionChanged 事件 |
✅ 完全对齐 |
| 尺寸 | ✅ 跟随全局 | ✅ SizeType 属性 |
✅ 完全对齐 |
继承关系
Avalonia.Controls.Primitives.TemplatedControl
└── AtomUI.Desktop.Controls.AbstractTransfer (abstract)
├── implements IMotionAwareControl
├── implements IInputControlStatusAware
├── implements ISizeTypeAware
├── AtomUI.Desktop.Controls.ListTransfer
└── AtomUI.Desktop.Controls.TreeTransfer
各层级职责划分:
| 层级 | 提供的能力 |
|---|---|
TemplatedControl |
模板化呈现、主题/样式支持 |
AbstractTransfer |
数据源管理、穿梭逻辑(源↔目标键集合操作)、搜索过滤、全选操作处理、布局配置(拉伸/固定宽度)、事件定义 |
ListTransfer |
列表视图默认创建(TransferListView)、分页支持(PageSize)、自定义 SourceView / TargetView |
TreeTransfer |
树视图默认创建(TransferTreeView)、树节点遮罩、目标面板扁平化计算 |
实现的共享接口:
| 接口 | 定义位置 | 作用 |
|---|---|---|
IMotionAwareControl |
AtomUI.Controls |
支持 IsMotionEnabled 动画开关 |
IInputControlStatusAware |
AtomUI.Controls.Shared |
支持 Status(Error/Warning)验证状态 |
ISizeTypeAware |
AtomUI.Controls.Shared |
支持 SizeType(Small/Middle/Large)尺寸切换 |
源码位置
| 层级 | 文件路径 | 说明 |
|---|---|---|
| 控件类 | src/AtomUI.Desktop.Controls/Transfer/AbstractTransfer.cs |
穿梭框抽象基类 |
| 控件类 | src/AtomUI.Desktop.Controls/Transfer/ListTransfer.cs |
列表穿梭框 |
| 控件类 | src/AtomUI.Desktop.Controls/Transfer/TreeTransfer.cs |
树形穿梭框 |
| 内部控件 | src/AtomUI.Desktop.Controls/Transfer/TransferItemDecorator.cs |
面板装饰器 |
| 内部控件 | src/AtomUI.Desktop.Controls/Transfer/TransferListView.cs |
列表视图 |
| 内部控件 | src/AtomUI.Desktop.Controls/Transfer/TransferTreeView.cs |
树视图 |
| 内部控件 | src/AtomUI.Desktop.Controls/Transfer/TransferSelectDropdown.cs |
选择操作下拉菜单 |
| 内部控件 | src/AtomUI.Desktop.Controls/Transfer/TransferRemoveItemButton.cs |
单向模式删除按钮 |
| 接口 | src/AtomUI.Desktop.Controls/Transfer/ITransferView.cs |
视图接口 |
| 接口 | src/AtomUI.Desktop.Controls/Transfer/ITransferTreeView.cs |
树视图接口 |
| 枚举 | src/AtomUI.Desktop.Controls/Transfer/TransferDirection.cs |
穿梭方向枚举 |
| 枚举 | src/AtomUI.Desktop.Controls/Transfer/TransferViewType.cs |
视图类型枚举 |
| 枚举 | src/AtomUI.Desktop.Controls/Transfer/TransferSelectAction.cs |
选择操作枚举 |
| 事件参数 | src/AtomUI.Desktop.Controls/Transfer/TransferSelectionChangedEventArgs.cs |
选择变更事件参数 |
| 事件参数 | src/AtomUI.Desktop.Controls/Transfer/TransferItemsRemovedEventArgs.cs |
项移除事件参数 |
| Token 定义 | src/AtomUI.Desktop.Controls/Transfer/TransferToken.cs |
组件级 Design Token |
| 本地化 | src/AtomUI.Desktop.Controls/Transfer/Localization/zh_CN.cs |
中文语言资源 |
| 本地化 | src/AtomUI.Desktop.Controls/Transfer/Localization/en_US.cs |
英文语言资源 |
| 主题模板 | src/AtomUI.Desktop.Controls/Transfer/Themes/AbstractTransferTheme.axaml |
抽象基类 ControlTheme |
| 主题模板 | src/AtomUI.Desktop.Controls/Transfer/Themes/ListTransferTheme.axaml |
列表穿梭框 ControlTheme |
| 主题模板 | src/AtomUI.Desktop.Controls/Transfer/Themes/TreeTransferTheme.axaml |
树穿梭框 ControlTheme |
| 主题模板 | src/AtomUI.Desktop.Controls/Transfer/Themes/TransferItemDecoratorTheme.axaml |
装饰器 ControlTheme |
| 主题注册 | src/AtomUI.Desktop.Controls/Transfer/Themes/TransferThemes.axaml |
主题资源合并 |
| Gallery 示例 | controlgallery/AtomUIGallery/ShowCases/Views/DataEntry/TransferShowCase.axaml |
使用范例 |
模板结构
ListTransfer / TreeTransfer 模板
Grid#RootLayout (三列布局)
├── TransferItemDecorator#SourceDecoratorView (Column=0) ← 源面板
├── StackPanel#ActionsLayout (Column=1) ← 穿梭操作按钮
│ ├── Button#ToTargetButton (→) ← 转移到目标
│ └── Button#ToSourceButton (←) ← 转移到源(单向模式隐藏)
└── TransferItemDecorator#TargetDecoratorView (Column=2) ← 目标面板
TransferItemDecorator 模板(面板装饰器)
Border#Frame ← 主框架(边框+圆角)
└── DockPanel#RootLayout ← 根布局
├── Border#HeaderFrame (Dock=Top) ← 头部信息栏
│ └── DockPanel#HeaderLayout
│ ├── CheckBox#SelectAllCheckBox ← 全选复选框
│ ├── TransferSelectDropdown#MenuIndicator ← 操作下拉菜单
│ ├── ContentPresenter#SelectedInfo ← 选中信息("2/10 items")
│ └── ContentPresenter#TitleContentPresenter ← 面板标题
├── LineEdit#FilterInput (Dock=Top) ← 搜索框(IsFilterEnabled 控制)
├── Border#FooterFrame (Dock=Bottom) ← 页脚区域
│ └── ContentPresenter#FooterPresenter
└── ContentPresenter#ContentPresenter ← 视图内容(ITransferView)