DirectSurface UIDirectSurface UI
开始使用
文档/组件手册

PropertyGrid 属性表

通用布局能力RenderPropertyGrid 实例统一支持 widthheight、min/max、margin 和槽位对齐;构造器是否接收这些字段以参数表为准。详见组件通用布局属性

LIVE CANVAS可运行组件示例
ON-DEMAND RUNTIME交互式示例将在进入视区时启动避免文档首屏同时初始化多个 Canvas Runtime

RenderPropertyGrid 用于展示和编辑对象属性。它适合打印设计器、报表设计器、控件检查器、配置面板等场景:左侧是属性名,右侧是当前值,并按 group 分组显示。

属性表本身不反射业务对象,也不直接保存业务模型。推荐做法是由业务层提供 PropertyGridRow[],或者使用轻量 schema API 把对象状态转换成 rows。提交时仍由业务层通过 onValueCommit 决定是否接受变更。

API 总览

import {  RenderPropertyGrid,  buildPropertyGridRows,  definePropertyGridSchema,  type PropertyGridField,  type PropertyGridRow,  type PropertyGridSchema,} from 'ds-ui'
API 类型 用途
RenderPropertyGrid class 属性表控件,负责分组绘制、滚动、选中、键盘导航和编辑请求。
PropertyGridRow type 单个属性行。
PropertyGridEditorKind type 编辑器类型,例如 text、number、boolean、enum、color、date、image-source。
buildPropertyGridRows() function 根据 schema 和上下文生成 PropertyGridRow[]
definePropertyGridSchema() function 定义属性 schema,主要用于保留泛型上下文。
PropertyGridSchema / PropertyGridField type 属性描述模型。

何时使用

  • 设计器右侧属性面板。
  • 对象检查器、调试面板、配置面板。
  • 需要按分组展示大量键值属性。
  • 需要 enum、boolean、color、date 等不同编辑入口。
  • 需要键盘上下移动选中行,并通过 Enter 或 F2 打开编辑。

不适合:

  • 多行业务数据维护。使用 GridView
  • 常规表单录入。使用 EntryGrid 或表单组件。
  • 树形对象结构浏览。使用 TreeView 或专用对象检查器。

最小示例

const grid = new RenderPropertyGrid({  rows: [    { group: 'Text', name: 'Text', value: '姓名', editable: true, editor: 'text', propPath: 'object.text' },    { group: 'Text', name: 'Color', value: '#111827', editable: true, editor: 'color', propPath: 'object.color' },    { group: 'Text', name: 'Wrap', value: 'true', editable: true, editor: 'boolean', propPath: 'object.wrap' },  ],  onEditRequested: (row, context) => {    // 打开文本、颜色、日期或枚举弹窗,并通过 context.commit() 提交。  },  onValueCommit: (row, nextValue) => {    // 更新业务对象;返回 false 可拒绝提交。    return true  },})

nameColumnWidth 用于设置属性名列的初始宽度,也可以在运行时通过同名属性读写。用户可直接拖动属性名与属性值之间的分隔线调整宽度;组件会为两侧保留最小可用宽度。

Schema 生成 rows

schema 是一个轻量适配层。它不要求业务对象有 attribute,也不做运行时反射;每个字段显式声明如何从当前上下文取值、显示、编辑和分组。

interface TextObjectContext {  object: {    text: string    color?: string    wrap?: boolean  }} const textObjectSchema = definePropertyGridSchema<TextObjectContext>([  {    group: 'Text',    name: 'Text',    propPath: 'object.text',    value: (context: TextObjectContext) => context.object.text,    editor: 'text',    editable: true,  },  {    group: 'Text',    name: 'Color',    propPath: 'object.color',    value: (context: TextObjectContext) => context.object.color ?? '#111827',    editor: 'color',    editable: true,  },  {    group: 'Text',    name: 'Wrap',    propPath: 'object.wrap',    value: (context: TextObjectContext) => context.object.wrap !== false,    editor: 'boolean',    editable: true,  },]) const object = {  text: '姓名',  color: '#111827',  wrap: true,} const rows = buildPropertyGridRows({ object }, textObjectSchema)

PropertyGridField 常用字段:

字段 说明
group / name 分组和属性名。
id 稳定行 id。存在同名属性时建议提供。
propPath 业务属性路径,提交、定位、错误映射常用。
value 静态值或 (context) => value
format 把原始值格式化为显示文本,例如 210 mm
editor 指定编辑器类型。
editable 是否可编辑,可根据上下文动态计算。
enumItems enum 编辑器的候选项。
visibleWhen 条件显示字段。
description / status / errorText 辅助说明和状态提示。
unit / step 数字编辑的单位和步进元数据。

交互行为

  • 单击属性行会选中当前行。
  • 拖动属性名列与属性值列之间的分隔线可调整两列宽度。
  • 属性名或属性值被截断时,悬浮会显示完整文本;未截断的内容不会显示冗余提示。
  • 单击 value 单元格会请求编辑可编辑文本、数字、枚举、颜色、日期等字段。
  • boolean 行可通过鼠标或 Space 直接切换。
  • ArrowUp 和 ArrowDown 在属性行之间移动选中项。
  • Enter 或 F2 对当前选中可编辑行发起编辑。
  • rowRectById() 可用稳定 id 获取弹窗锚点,避免同组同名属性定位错误。

属性说明面板

设置 showDescriptionPanel: true 后,PropertyGrid 会在底部显示当前选中属性的名称、description 和状态信息。鼠标点击属性或通过 ArrowUp、ArrowDown 切换属性时,说明同步更新;悬浮只负责属性名和值的截断提示,不会改变说明内容。

const grid = new RenderPropertyGrid({  showDescriptionPanel: true,  descriptionEmptyText: '选择属性查看用途和取值规则。',  selectedRowId: 'maximum-decimals',  rows: [{    id: 'maximum-decimals',    group: 'Format',    name: 'Maximum Decimals',    value: '2',    description: '格式化结果最多保留的小数位数。超过的部分会按照当前数值格式执行四舍五入。',  }],})

说明面板按可用宽度对标题、说明和 errorText 完整换行,并根据实际行数自动调整高度,不使用省略号或依赖 Tooltip。PropertyGrid 高度不足时会优先保留可操作的属性列表区域;只有完整说明确实无法同时放下时,说明正文才启用独立滚动。

属性列表与说明面板之间的横向分隔条支持拖动:

  • 默认使用自动高度。
  • 拖动分隔条后进入当前实例的手动高度模式。
  • 双击分隔条或调用 resetDescriptionPanelHeight() 恢复自动高度。
  • 宽度、选中属性或 rows 变化后,自动模式会重新测量完整说明。

showDescriptionPanel 默认为 false,因此现有 PropertyGrid 不会因为升级而改变布局。属性密集、业务含义复杂的设计器和检查器应显式开启。

编辑器协议

PropertyGrid 不依赖 JS attribute,也不反射业务对象。编辑入口由每一行的 editor 字段声明,再通过 editorHandlers、内建编辑器或 onEditRequested 执行。

const grid = new RenderPropertyGrid({  rows: [    { group: 'Image', name: 'Source', value: '', editable: true, editor: 'image-source', propPath: 'object.source' },  ],  editorHandlers: {    'image-source': context => {      // 可覆盖内建图片选择行为,例如接入资源库。      context.commit('data:image/png;base64,...')    },  },  onEditRequested: (row, context) => {    // 处理 text、number、color、date、expression 等宿主自定义弹窗。    context.commit(row.value)  },  onEditError: (row, message) => {    // 把编辑错误映射回业务状态或属性行错误。  },})

编辑处理优先级:

  1. editorHandlers[editor]:开发者显式接管某类编辑器。
  2. 内建编辑器:当前内建 image-source,会打开本地图片选择并读取为 base64 image data URI。
  3. onEditRequested(row, context):宿主打开自己的弹窗或编辑器。

编辑处理函数是同步接管协议:返回 false 表示当前处理器不处理,PropertyGrid 会继续尝试后续处理器;返回 true 或不返回值表示已经接管。需要异步工作的编辑器,例如文件选择、资源库弹窗或外部对话框,应在处理器内部启动异步流程,并在完成后调用 context.commit()context.setError()

PropertyGridEditContext 提供:

字段 说明
row / editor 当前属性行和编辑器类型。
commit(nextValue) 提交值,会继续走 onValueCommit 校验。
updateDisplayValue(value) 只更新属性表显示值,不提交业务对象。
setError(message) 通知宿主编辑失败。

image-source 的内建行为只负责本地文件选择和 FileReader.readAsDataURL() 转换。它提交的是 data:image/...;base64,...;业务层仍应在 onValueCommit 中决定是否接受该值。远程 URL 不属于这个内建编辑器的默认契约。

设计边界

RenderPropertyGrid 只处理通用交互和展示。业务应该负责:

  • 根据当前对象生成 rows。
  • 根据 propPathid 提交变更。
  • 打开具体编辑器弹窗。
  • 校验输入并把错误映射回属性行。

这种边界让属性表可以同时服务打印设计器、医疗编辑器和普通业务配置面板,而不需要引入语言级 attribute 或业务反射模型。