You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
129 lines
4.1 KiB
129 lines
4.1 KiB
|
1 month ago
|
# NodeCanvas 节点显示问题修复记录
|
||
|
|
|
||
|
|
## 问题描述
|
||
|
|
|
||
|
|
在节点编辑器页面中,`InitializeTestNode` 执行后节点已成功添加到服务,位置也设置成功,但画布上不显示节点。
|
||
|
|
|
||
|
|
## 问题现象
|
||
|
|
|
||
|
|
从日志可以看到:
|
||
|
|
- 节点已成功添加到 `Nodes` 集合(`ViewModel.Nodes.Count = 1`)
|
||
|
|
- 节点位置已正确设置(位置: (100, 100))
|
||
|
|
- ContentPresenter 可见性为 `True`
|
||
|
|
- 但是 **Canvas 面板大小为 0x0**,导致节点不可见
|
||
|
|
|
||
|
|
```
|
||
|
|
[节点更新] Canvas 面板大小: 0x0
|
||
|
|
[节点更新] Canvas 子元素: ContentPresenter, 位置: (100, 100), 可见: True, 大小: 120x112
|
||
|
|
```
|
||
|
|
|
||
|
|
## 根本原因
|
||
|
|
|
||
|
|
在 Avalonia 中,当使用 `ItemsControl` 和 `Canvas` 作为 `ItemsPanel` 时,存在以下问题:
|
||
|
|
|
||
|
|
1. **Canvas 大小问题**:`ItemsControl` 使用的 `Canvas`(作为 `ItemsPanel`)不会自动计算大小,默认为 0x0,导致节点虽然位置正确但不可见。
|
||
|
|
|
||
|
|
2. **位置绑定缺失**:需要在 `ItemTemplate` 的根元素上绑定 `Canvas.Left` 和 `Canvas.Top` 属性,而不是仅依赖代码后台手动设置。
|
||
|
|
|
||
|
|
## 解决方案
|
||
|
|
|
||
|
|
### 1. 设置 Canvas 明确大小
|
||
|
|
|
||
|
|
在 `ItemsPanelTemplate` 的 `Canvas` 上设置明确的大小:
|
||
|
|
|
||
|
|
```xml
|
||
|
|
<ItemsControl.ItemsPanel>
|
||
|
|
<ItemsPanelTemplate>
|
||
|
|
<Canvas ClipToBounds="False"
|
||
|
|
MinWidth="2000"
|
||
|
|
MinHeight="2000"
|
||
|
|
Width="2000"
|
||
|
|
Height="2000"/>
|
||
|
|
</ItemsPanelTemplate>
|
||
|
|
</ItemsControl.ItemsPanel>
|
||
|
|
```
|
||
|
|
|
||
|
|
**关键点**:Canvas 必须设置明确的大小,不能依赖自动计算。
|
||
|
|
|
||
|
|
### 2. 添加位置数据绑定
|
||
|
|
|
||
|
|
在 `ItemTemplate` 的根元素(`Border`)上绑定位置:
|
||
|
|
|
||
|
|
```xml
|
||
|
|
<Border Background="White"
|
||
|
|
CornerRadius="6"
|
||
|
|
...
|
||
|
|
Canvas.Left="{Binding X}"
|
||
|
|
Canvas.Top="{Binding Y}">
|
||
|
|
```
|
||
|
|
|
||
|
|
**关键点**:位置绑定应该在 `ItemTemplate` 的根元素上,数据绑定会自动处理位置更新。
|
||
|
|
|
||
|
|
### 3. ItemsControl 布局设置
|
||
|
|
|
||
|
|
为 `ItemsControl` 添加对齐属性:
|
||
|
|
|
||
|
|
```xml
|
||
|
|
<ItemsControl x:Name="NodesItemsControl"
|
||
|
|
ItemsSource="{Binding Nodes}"
|
||
|
|
HorizontalAlignment="Stretch"
|
||
|
|
VerticalAlignment="Stretch">
|
||
|
|
```
|
||
|
|
|
||
|
|
### 4. 代码后台位置更新(备用方案)
|
||
|
|
|
||
|
|
保留代码后台的手动位置更新作为备用方案,确保在某些情况下位置也能正确设置。
|
||
|
|
|
||
|
|
## 技术要点
|
||
|
|
|
||
|
|
### Avalonia 与 WPF 的差异
|
||
|
|
|
||
|
|
在 Avalonia 中:
|
||
|
|
- `ItemsControl` 使用 `Canvas` 作为 `ItemsPanel` 时,Canvas **不会自动计算大小**
|
||
|
|
- 必须显式设置 Canvas 的 `Width` 和 `Height`
|
||
|
|
- 位置绑定应该在 `ItemTemplate` 的根元素上,而不是在容器上
|
||
|
|
|
||
|
|
### 最佳实践
|
||
|
|
|
||
|
|
1. **数据绑定优先**:使用 XAML 数据绑定处理位置更新,而不是代码后台手动设置
|
||
|
|
2. **明确大小**:Canvas 必须设置明确的大小,建议与父容器保持一致
|
||
|
|
3. **备用方案**:保留代码后台的位置更新作为备用,但主要依赖数据绑定
|
||
|
|
|
||
|
|
## 修改文件
|
||
|
|
|
||
|
|
- `AuroraDesk.Presentation/Views/Pages/NodeCanvasPageView.axaml`
|
||
|
|
- 在 `ItemsPanelTemplate` 的 `Canvas` 上设置大小
|
||
|
|
- 在 `ItemTemplate` 的 `Border` 上添加 `Canvas.Left` 和 `Canvas.Top` 绑定
|
||
|
|
- 为 `ItemsControl` 添加对齐属性
|
||
|
|
|
||
|
|
- `AuroraDesk.Presentation/Views/Pages/NodeCanvasPageView.axaml.cs`
|
||
|
|
- 保留位置更新代码作为备用方案
|
||
|
|
- 添加调试信息帮助诊断问题
|
||
|
|
|
||
|
|
## 验证
|
||
|
|
|
||
|
|
修复后,节点应该能够正常显示在画布上:
|
||
|
|
- Canvas 面板大小不再是 0x0
|
||
|
|
- 节点位置正确显示
|
||
|
|
- 节点可以正常交互(拖拽、选择等)
|
||
|
|
|
||
|
|
## 相关日志
|
||
|
|
|
||
|
|
修复前的关键日志:
|
||
|
|
```
|
||
|
|
[节点更新] Canvas 面板大小: 0x0
|
||
|
|
[节点更新] Canvas 子元素: ContentPresenter, 位置: (100, 100), 可见: True, 大小: 120x112
|
||
|
|
```
|
||
|
|
|
||
|
|
修复后应该看到:
|
||
|
|
```
|
||
|
|
[节点更新] Canvas 面板大小: 2000x2000
|
||
|
|
[节点更新] Canvas 子元素: ContentPresenter, 位置: (100, 100), 可见: True, 大小: 120x112
|
||
|
|
```
|
||
|
|
|
||
|
|
## 参考资料
|
||
|
|
|
||
|
|
- [Avalonia ItemsControl 文档](https://docs.avaloniaui.net/docs/guides/controls/itemscontrol)
|
||
|
|
- [Avalonia Canvas 布局](https://docs.avaloniaui.net/docs/guides/controls/canvas)
|
||
|
|
|