假设我有一个
Form
并且它包含一个 ToolStrip
。在 Form1.Designer.cs
文件中,我可以看到以下行:
this.toolStrip1.ResumeLayout(false);
this.toolStrip1.PerformLayout();
假设我使用以下代码生成自定义 ToolStrip:
[Designer(typeof(System.Windows.Forms.Design.ControlDesigner))]
public class MyToolStrip : ToolStrip
{
}
参见 WinForms ToolStrip 在视觉继承中不可用
如果我现在在
MyToolStrip
中使用 ToolStrip
而不是 Form
,那么 this.toolStrip1.PerformLayout()
行将从设计器文件中删除。为什么?我怎样才能把它带回来,而不需要每次编辑我不应该做的设计器文件?
如果该行缺失,则某些控件的大小不正确,例如:
ToolStripComboBox
另请参阅 C#:ResumeLayout(true) 与 ResumeLayout(false) + PerformLayout() 的作用相同吗?
前言:这是基于我的理解,您希望对 ToolStrip 控件使用视觉继承,但允许继承的表单修改 ToolStrip 的“Items”属性,该属性通常在派生表单中不可编辑。
警告:这是一项完整的黑客工作,我还没有评估实现用于获得所需结果的技巧的后果。
----------
正如评论中提到的,ControlDesigner类的属性
SerializePerformLayout
返回“false”,而ToolStripDesigner类的属性SerializePerformLayout
返回“true”。 该属性在 ToolStripCodeDomSerializer 类的 Serialize
方法中使用(实际上该方法是从 ControlCodeDomSerializer 类继承的)。 具体在这段代码片段中:
if (HasAutoSizedChildren(control) || (controlDesigner is not null && controlDesigner.SerializePerformLayout))
{
SerializePerformLayout(manager, csCollection, value);
}
由于无法覆盖
controlDesigner.SerializePerformLayout
,因此我们必须找到一种方法使 HasAutoSizedChildren(control)
评估为 true。 一种方法是将隐藏控件添加到 ToolStrip 的控件集合中。
public MyToolStrip() : base()
{
Control c = new Control();
c.Visible = false;
c.MinimumSize = System.Drawing.Size.Empty;
c.Size = System.Drawing.Size.Empty;
c.AutoSize = true;
Controls.Add(c);
}
通常,ToolStrip 不是父控件,而是从 ToolStripItem 类派生的组件。事实上,它的
ControlCollection
是只读的。 为了解决这个问题,我们需要重写 CreateControlsInstance
方法。
protected override Control.ControlCollection CreateControlsInstance()
{
return new ControlCollection(this);
}
总结一下:
[Designer("System.Windows.Forms.Design.ControlDesigner, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")]
public class MyToolStrip : ToolStrip
{
public MyToolStrip() : base()
{
Control c = new Control();
c.Visible = false;
c.MinimumSize = System.Drawing.Size.Empty;
c.Size = System.Drawing.Size.Empty;
c.AutoSize = true;
Controls.Add(c);
}
protected override Control.ControlCollection CreateControlsInstance()
{
return new ControlCollection(this);
}
}
您仍然需要在基本表单的设计器中将 ToolStrip 的
Modifiers
属性设置为 Protected
。