窗口隐藏(`Visibility.Hidden`)期间实例化的 `hc:Divider` 分隔线渲染宽度为 0
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 85/100
Research direction
Start in src/Shared/HandyControl_Shared/Controls/Panel/Grid/Row.cs, focusing on ArrangeOverride and the child-visibility check. Run the supplied DividerTest reproduction with the hidden-window sequence, then verify that the affected Col elements receive their arrangement after the window is shown. Done means Divider lines and content render normally after restoration.
Written by the indexing model from the issue text.
Description
Describe the bug
当宿主窗口处于 Visibility.Hidden 状态(典型的 「最小化到托盘」 场景)时,如果有 hc:Divider(或任何以 hc:Row/hc:Col 为模板根的控件)的模板在此期间被实例化并加入可视化树,这些元素会永久渲染失败:
Divider控件本身能拿到正常的布局尺寸(例如 420×15);- 但其模板内的三个
hc:Col(左线 / 内容 / 右线)的ActualWidth/ActualHeight均保持 0,视觉上完全不显示; - 窗口恢复
Visible后不会自愈,手动调用InvalidateMeasure/InvalidateArrange/UpdateLayout也无法恢复; - 使用标准
Grid/Border模板的元素在同样时序下显示正常,因此该问题特定于Row/Col栅格。
Steps to reproduce the bug
最小复现工程
DividerTest.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net10.0-windows10.0.17763.0</TargetFramework>
<Nullable>enable</Nullable>
<UseWPF>true</UseWPF>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="HandyControl" Version="3.6.0-rc3" />
</ItemGroup>
</Project>
App.xaml
<Application x:Class="DividerTest.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/HandyControl;component/Themes/SkinDefault.xaml" />
<ResourceDictionary Source="pack://application:,,,/HandyControl;component/Themes/Theme.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
MainWindow.xaml
<Window x:Class="DividerTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:hc="https://handyorg.github.io/handycontrol"
Title="Divider repro" Width="900" Height="600">
<Window.Resources>
<DataTemplate x:Key="LogTemplate">
<hc:Divider MaxWidth="420" HorizontalContentAlignment="Center"
Content="{Binding}" />
</DataTemplate>
</Window.Resources>
<ScrollViewer HorizontalScrollBarVisibility="Disabled">
<ItemsControl x:Name="LogList" ItemTemplate="{StaticResource LogTemplate}" />
</ScrollViewer>
</Window>
MainWindow.xaml.cs
using System;
using System.Windows;
using System.Windows.Threading;
namespace DividerTest;
public partial class MainWindow
{
public MainWindow()
{
InitializeComponent();
// 1s 后添加第一个 divider,随即最小化并隐藏窗口(模拟最小化到托盘)
var t1 = new DispatcherTimer { Interval = TimeSpan.FromSeconds(1) };
t1.Tick += (s, e) =>
{
t1.Stop();
LogList.Items.Add("A: 添加后立即隐藏");
WindowState = WindowState.Minimized;
ShowInTaskbar = false;
Visibility = Visibility.Hidden;
// 2s 后(窗口仍隐藏)再添加一个
var t2 = new DispatcherTimer { Interval = TimeSpan.FromSeconds(2) };
t2.Tick += (s2, e2) =>
{
t2.Stop();
LogList.Items.Add("B: 隐藏期间添加");
// 2s 后恢复窗口
var t3 = new DispatcherTimer { Interval = TimeSpan.FromSeconds(2) };
t3.Tick += (s3, e3) =>
{
t3.Stop();
Show();
WindowState = WindowState.Normal;
Activate();
};
t3.Start();
};
t2.Start();
};
t1.Start();
}
}
运行后观察:窗口恢复显示时,两个 divider 都不渲染(分隔线与文字均不显示)。触发条件是 「模板实例化(首次布局展开)发生在窗口 Hidden 期间」——第一个 divider 虽然是在窗口可见时添加的,但其模板展开前窗口已被隐藏,同样复现。
Expected behavior
窗口恢复 Visible 后,hc:Divider 应正常渲染出分隔线与内容;即使模板在窗口隐藏期间实例化,布局也应在窗口恢复后自动恢复正常。
Screenshots
见附件 screenshot.png(同一 DataTemplate、同一时序下的对照):hc:Divider 原始模板的行完全空白;带 [fix] 标记的行是仅把模板根 hc:Row 替换为修复版子类(见 Additional context)后的效果,分隔线正常。
NuGet package version
HandyControl 3.5.1
IDE
No response
Framework type
No response
Windows version
No response
Additional context
根因分析
Row.ArrangeOverride(src/Shared/HandyControl_Shared/Controls/Panel/Grid/Row.cs):
protected override Size ArrangeOverride(Size finalSize)
{
...
foreach (var child in cols)
{
if (!child.IsVisible) // ← 问题所在
{
continue;
}
...
child.Arrange(childBounds);
}
return finalSize;
}
当模板在宿主窗口 Hidden 期间实例化时,布局过程中 hc:Col 的 IsVisible 为 false(受祖先窗口隐藏状态影响),这些 Col 被 continue 跳过、从未被 Arrange。窗口恢复可见后,被跳过 Arrange 的 Col 布局状态无法再恢复(InvalidateMeasure/InvalidateArrange 均无效),ActualWidth/ActualHeight 永久保持 0。Measure 阶段是正常的(Col 的 DesiredSize 与可见时添加的完全一致),仅 Arrange 失败。
诊断数据(窗口恢复显示后读取可视化树):
[hc:Divider 原始] Divider Actual=420.0x15.2, Line ActualW=0.0
Row: _fixedWidth=81.0, RenderSize=420.0x15.2
col[0] Col: Desired=169.3x1.0, Actual=0.0x0.0
col[1] Col: Desired=81.0x15.2, Actual=0.0x0.0
col[2] Col: Desired=169.3x1.0, Actual=0.0x0.0
[MyRow 修复版] Divider Actual=420.0x15.2, Line ActualW=169.7
建议修复(已验证)
将 Row.ArrangeOverride 中的检查改为读取元素自身的 Visibility 属性(不受祖先窗口隐藏状态影响):
if (child.Visibility != Visibility.Visible)
{
continue;
}
已通过子类化 Row 覆写 ArrangeOverride(仅替换这一处判断,其余逻辑与 3.6.0-rc3 完全一致)验证:同一 DataTemplate、同一时序下,原始版 Line ActualW = 0,修复版 Line ActualW ≈ 169,分隔线与内容均正常渲染。
实际影响场景
任何 「最小化到托盘」 的应用(WindowState = Minimized + Visibility = Hidden)在隐藏期间动态添加 hc:Divider(或 Row/Col 栅格)内容——例如日志分区线、运行时生成的分区 UI——都会触发,且该元素此后永久不可见。
- Dominant language
- C#
- Stars
- 7.2k
- Forks
- 1.2k
- PR merge metrics
- No merged PRs in 30d
Getting set up
This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from HandyOrg/HandyControl
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
HandyOrg/HandyControl#1809 ·
-
Difficulty 3/5 1-2 days Newbie friendliness 45/100
HandyOrg/HandyControl#1820 ·
-
不能够独立的引入用户认为需要的部分Open
Difficulty 4/5 3-5 days Newbie friendliness 48/100
HandyOrg/HandyControl#1816 · 1 comment ·
-
Difficulty 3/5 1-2 days Newbie friendliness 45/100
HandyOrg/HandyControl#1813 ·
-
Difficulty 3/5 1-2 days Newbie friendliness 55/100
HandyOrg/HandyControl#1803 ·
All issues in HandyOrg/HandyControl
Similar issues
-
area/navigationview 🧭 difficulty/starter 🚀 good first issue kind/bug platform/all project/navigation-lifecycle 🧬 triage/untriaged
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
unoplatform/uno#24925 · 1 comment ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
DamianEdwards/ghcp-spend-tray#39 ·
Maintainers usually reply within 1 day
-
copilot documentation
Difficulty 1/5 1-3 hours Newbie friendliness 88/100
Maintainers usually reply within 2 days
-
[Rust][Flaky Test] multiple_deadlines_fire_in_order asserts a wall-clock gap instead of firing orderOpenCI/CD ⚒️ Flaky-tests 🐦
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
valkey-io/valkey-glide#7255 ·
Maintainers usually reply within 3 days
-
bug good first issue
Difficulty 1/5 Under an hour Newbie friendliness 92/100
unoplatform/Uno.Core#99 ·