Debugger Visualizer Winform ToolStripDropDownMenu ComboBox 仅在首次显示时显示项目
Debugger Visualizer Winform ToolStripDropDownMenu ComboBox only shows items when first shown
我有一个 Visual Studio 调试器可视化程序项目,当我将 ToolStripComboBox
添加到 ToolStripDropDownMenu
时,组合框的项目仅在第一次显示表单时出现。
像这样:
显示问题的最基本版本的 winform 代码是这样的:
public class MyVisualizerDialog : Form
{
public MyVisualizerDialog()
{
var toolStripComboBox = new ToolStripComboBox
{
Items = { "One", "Two", "Three" }
};
var toolStripDownDown = new ToolStripDropDownMenu
{
Items = { toolStripComboBox }
};
var toolStrip = new ToolStrip
{
Items =
{
new ToolStripMenuItem("Options")
{
DropDown = toolStripDownDown
}
}
};
Controls.Add(toolStrip);
}
}
那么可视化代码就是:
public class MyVisualizer : DialogDebuggerVisualizer
{
protected override void Show(
IDialogVisualizerService windowService,
IVisualizerObjectProvider objectProvider)
{
windowService.ShowDialog(
new MyVisualizerDialog());
}
}
一些额外的细节:
如果我将 ToolStripComboBox
添加到 ToolStripMenuItem.DropDownItems
,它工作正常 - 在 [=17] 中添加 ToolStripComboBox
似乎是一个问题=].
如果我在控制台应用程序中创建并打开相同表单 class 的多个实例,它工作正常。
一旦问题发生,它 保持 发生 - 即使我将代码恢复到没有 ToolStripDropDown
的版本
如果我重新启动 Visual Studio,它在第一次显示表单时有效,之后就不行了。
有什么想法吗?!任何人都知道 IDialogVisualizerService
处理控件或其他方式的一些问题?!
感谢阅读:)
看起来,当调试器可视化器关闭时 - 这是在调试器端处理的,而不是在调试器端处理的 - DropDown 被破坏但 ToolStripManager 不知道它并且它发现本身带有一个它不知道如何管理的无效句柄。
由于 ToolStripManager 在设计模式下也处于活动状态,这会在整个设计器界面传播问题:您可能会发现某些 DropDown 项目在调试器可视化工具关闭后仍然有效,但您可能无法添加其他项目ToolStripComboBox 项在任何地方。
如果你坚持,那么那些看起来有效的可能不再有效。
请注意,此错误行为可能会转化为 ComboBox 对象;不是直接,而是当您尝试通过界面访问他们的 Items 集合时。
它还可能会阻止项目编译。
显式处理在调试器可视化器端创建的 Form 对象,可以部分解决调试器端的问题,但事实证明,在调试器可视化器端并不能解决问题。
一个简单的解决方案是避免设置 ToolStripMenuItem 的 DropDown 对象,而是使用 MenuStrip,将 Items 添加到 ToolStripDownDown。
Create custom data visualizers
Visualizer Security Considerations
示例调试器可视化工具(简单图像可视化工具),用于测试好和坏行为。
▶ 创建一个 Class 图书馆项目,Target Framework
设置为 .Net Framework
,AnyCPU
配置文件。
▶ 添加对 [Visual Studio install Path]\Common7\IDE\PublicAssemblies\Microsoft.VisualStudio.DebuggerVisualizers.dll
和 System.Windows.Forms
的引用。
▶ 将 .dll 编译为 Release
。
▶ 将 .dll 复制到当前 Visual Studio 安装路径的 \Common7\Packages\Debugger\Visualizers
目录。
▶ 启动调试会话,在 Image/Bitmap 属性 为 set/loaded 的位置添加断点,然后使用放大镜工具打开预览。
using System.Diagnostics;
using System.Drawing;
using System.Windows.Forms;
using Microsoft.VisualStudio.DebuggerVisualizers;
[assembly: DebuggerVisualizer(
typeof(ImageVisualizer.DebuggerSide),
typeof(VisualizerObjectSource), Target = typeof(Image), Description = "Test Visualizer")]
namespace TestVisualizer
{
public class DebuggerSide : DialogDebuggerVisualizer
{
override protected void Show(IDialogVisualizerService windowService, IVisualizerObjectProvider objectProvider)
{
var image = (Image)objectProvider.GetObject();
var form = new Form();
form.ClientSize = new Size(image.Width, image.Height);
form.FormBorderStyle = FormBorderStyle.FixedSingle;
form.SuspendLayout();
// ------- WORKING CODE ---------------
var menuStrip = new MenuStrip() { };
var tsComboBox = new ToolStripComboBox { Items = { "One", "Two", "Three" } };
var toolStripDownDown = new ToolStripMenuItem() { Text = "Options" };
toolStripDownDown.DropDownItems.AddRange(new ToolStripItem[] { tsComboBox });
menuStrip.Items.AddRange(new ToolStripItem[] { toolStripDownDown });
// ------- WORKING CODE ---------------
// ------- BAD CODE ---------------
//var toolStripComboBox = new ToolStripComboBox { Items = { "One", "Two", "Three" } };
//var toolStripDownDown = new ToolStripDropDownMenu { Items = { toolStripComboBox } };
//var toolStrip = new ToolStrip {
// Items = { new ToolStripMenuItem("Options") { DropDown = toolStripDownDown } }
//};
// ------- BAD CODE ---------------
var pBox = new PictureBox() { Image = image, Dock = DockStyle.Fill };
//form.Controls.Add(toolStrip);
form.Controls.Add(menuStrip);
form.Controls.Add(pBox);
form.MainMenuStrip = menuStrip;
form.ResumeLayout(false);
form.PerformLayout();
windowService.ShowDialog(form);
form?.Dispose();
}
}
}
我有一个 Visual Studio 调试器可视化程序项目,当我将 ToolStripComboBox
添加到 ToolStripDropDownMenu
时,组合框的项目仅在第一次显示表单时出现。
像这样:
显示问题的最基本版本的 winform 代码是这样的:
public class MyVisualizerDialog : Form
{
public MyVisualizerDialog()
{
var toolStripComboBox = new ToolStripComboBox
{
Items = { "One", "Two", "Three" }
};
var toolStripDownDown = new ToolStripDropDownMenu
{
Items = { toolStripComboBox }
};
var toolStrip = new ToolStrip
{
Items =
{
new ToolStripMenuItem("Options")
{
DropDown = toolStripDownDown
}
}
};
Controls.Add(toolStrip);
}
}
那么可视化代码就是:
public class MyVisualizer : DialogDebuggerVisualizer
{
protected override void Show(
IDialogVisualizerService windowService,
IVisualizerObjectProvider objectProvider)
{
windowService.ShowDialog(
new MyVisualizerDialog());
}
}
一些额外的细节:
如果我将
ToolStripComboBox
添加到ToolStripMenuItem.DropDownItems
,它工作正常 - 在 [=17] 中添加ToolStripComboBox
似乎是一个问题=].如果我在控制台应用程序中创建并打开相同表单 class 的多个实例,它工作正常。
一旦问题发生,它 保持 发生 - 即使我将代码恢复到没有
的版本ToolStripDropDown
如果我重新启动 Visual Studio,它在第一次显示表单时有效,之后就不行了。
有什么想法吗?!任何人都知道 IDialogVisualizerService
处理控件或其他方式的一些问题?!
感谢阅读:)
看起来,当调试器可视化器关闭时 - 这是在调试器端处理的,而不是在调试器端处理的 - DropDown 被破坏但 ToolStripManager 不知道它并且它发现本身带有一个它不知道如何管理的无效句柄。
由于 ToolStripManager 在设计模式下也处于活动状态,这会在整个设计器界面传播问题:您可能会发现某些 DropDown 项目在调试器可视化工具关闭后仍然有效,但您可能无法添加其他项目ToolStripComboBox 项在任何地方。
如果你坚持,那么那些看起来有效的可能不再有效。
请注意,此错误行为可能会转化为 ComboBox 对象;不是直接,而是当您尝试通过界面访问他们的 Items 集合时。
它还可能会阻止项目编译。
显式处理在调试器可视化器端创建的 Form 对象,可以部分解决调试器端的问题,但事实证明,在调试器可视化器端并不能解决问题。
一个简单的解决方案是避免设置 ToolStripMenuItem 的 DropDown 对象,而是使用 MenuStrip,将 Items 添加到 ToolStripDownDown。
Create custom data visualizers
Visualizer Security Considerations
示例调试器可视化工具(简单图像可视化工具),用于测试好和坏行为。
▶ 创建一个 Class 图书馆项目,Target Framework
设置为 .Net Framework
,AnyCPU
配置文件。
▶ 添加对 [Visual Studio install Path]\Common7\IDE\PublicAssemblies\Microsoft.VisualStudio.DebuggerVisualizers.dll
和 System.Windows.Forms
的引用。
▶ 将 .dll 编译为 Release
。
▶ 将 .dll 复制到当前 Visual Studio 安装路径的 \Common7\Packages\Debugger\Visualizers
目录。
▶ 启动调试会话,在 Image/Bitmap 属性 为 set/loaded 的位置添加断点,然后使用放大镜工具打开预览。
using System.Diagnostics;
using System.Drawing;
using System.Windows.Forms;
using Microsoft.VisualStudio.DebuggerVisualizers;
[assembly: DebuggerVisualizer(
typeof(ImageVisualizer.DebuggerSide),
typeof(VisualizerObjectSource), Target = typeof(Image), Description = "Test Visualizer")]
namespace TestVisualizer
{
public class DebuggerSide : DialogDebuggerVisualizer
{
override protected void Show(IDialogVisualizerService windowService, IVisualizerObjectProvider objectProvider)
{
var image = (Image)objectProvider.GetObject();
var form = new Form();
form.ClientSize = new Size(image.Width, image.Height);
form.FormBorderStyle = FormBorderStyle.FixedSingle;
form.SuspendLayout();
// ------- WORKING CODE ---------------
var menuStrip = new MenuStrip() { };
var tsComboBox = new ToolStripComboBox { Items = { "One", "Two", "Three" } };
var toolStripDownDown = new ToolStripMenuItem() { Text = "Options" };
toolStripDownDown.DropDownItems.AddRange(new ToolStripItem[] { tsComboBox });
menuStrip.Items.AddRange(new ToolStripItem[] { toolStripDownDown });
// ------- WORKING CODE ---------------
// ------- BAD CODE ---------------
//var toolStripComboBox = new ToolStripComboBox { Items = { "One", "Two", "Three" } };
//var toolStripDownDown = new ToolStripDropDownMenu { Items = { toolStripComboBox } };
//var toolStrip = new ToolStrip {
// Items = { new ToolStripMenuItem("Options") { DropDown = toolStripDownDown } }
//};
// ------- BAD CODE ---------------
var pBox = new PictureBox() { Image = image, Dock = DockStyle.Fill };
//form.Controls.Add(toolStrip);
form.Controls.Add(menuStrip);
form.Controls.Add(pBox);
form.MainMenuStrip = menuStrip;
form.ResumeLayout(false);
form.PerformLayout();
windowService.ShowDialog(form);
form?.Dispose();
}
}
}