为啥 WinForms 中的 TreeView 会意外崩溃?
Posted
技术标签:
【中文标题】为啥 WinForms 中的 TreeView 会意外崩溃?【英文标题】:Why would a TreeView collapse unexpectedly in WinForms?为什么 WinForms 中的 TreeView 会意外崩溃? 【发布时间】:2010-11-12 18:05:10 【问题描述】:除了调用 TreeNode 上的 .Collapse() 方法或 TreeView 的 .CollapseAll() 方法之外,还有什么会导致 TreeView 崩溃?
在我正在开发的应用程序中,TreeView 将无法正常运行。 TreeView 只维护两个级别。选择父节点的子节点时,所有其他节点都会立即折叠。但是,我的代码中没有任何 .Collapse() 或 .CollapseAll() 方法调用!
TreeView 的所有属性都保留为默认值,但 .LabelEdit 属性设置为 true。 TreeView 有一些与 AfterLabelEdit 事件相关联的代码,用于简单的验证/消息框例程。
我试过了:
挂钩的 BeforeCollapse 事件 TreeView 和提高 e.CancelAction 标志。
手动扩展所有节点 在 TreeView 的 AfterSelect 中 事件。 (这作为 实验,但我不打算 禁止节点折叠 完全!)
在代码中的很多地方,我都在逐个节点地遍历 TreeView 以检查属性。但是,不会发生节点的添加或删除。在用户进行选择时修改的唯一 TreeNode 属性是 .ImageIndex 和 .SelectedImageIndex。
除了上述两种解决方案之外,我不知道是什么导致了这个错误。即使无法实现任何解决方案,是否有人知道捕获崩溃的正确方法? (我尝试在 BeforeCollapse 事件中设置断点,但除非用户通过鼠标或键盘显式折叠节点,否则它不会触发。)
更新:
问题是由于更改了任何 TreeNode 上的 .SelectedImageIndex 属性。更改此属性会导致所有其他节点折叠。
我尝试使用 .BeginUpdate() 和 .EndUpdate() 调用来包围 .SelectedImageIndex 属性修改代码,但无济于事。
如何避免这种情况?
【问题讨论】:
【参考方案1】:这是本机窗口在 Windows 中工作方式的副作用。许多窗口选项由 CreateWindowEx() 调用中的样式标志指定。基本的东西,比如表单上的边框。 ListView 应该有什么样的 View。 TreeView 是否应该显示复选框。
这些样式作为控件的属性公开。但是有一个问题。更改此类属性需要从头开始重新创建窗口,以便可以在 CreateWindowEx() 调用中指定新的样式标志。这有副作用,窗口会被完全重新创建,因此它会丢失所有以前的状态。
Windows 窗体在使这看起来平滑方面做得很好,在重新创建窗口后恢复了以前的状态。但是这里和那里都有泄漏。还有一些彻头彻尾的错误。 TreeView 中的一个泄漏是哪些节点被折叠而哪些没有被折叠的确切状态。跟踪这一点是不切实际的。
通过将 TreeView 的 Handle 属性放在监视窗口中来诊断此问题。如果您看到它发生了变化,那么您已经找到了该属性。样式标志列表可用here, 您可能可以将它们的名称映射到它们相应的属性。
也许很明显,除了避免更改该属性之外,对于这个问题没有很好的解决方法。 WPF 就是这样的麻烦。
【讨论】:
感谢您的全面回答!我能够查明导致树被重新创建的属性,并避免在初始化点之后使用它。树不再忘记节点状态。 @HansPassant 我可以知道你为什么回滚我的编辑吗?谢谢以上是关于为啥 WinForms 中的 TreeView 会意外崩溃?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 WinForms 中禁用 TreeView 的节点重命名?
在 C# winforms 应用程序中使用文本框过滤 Treeview