关于WinForm自定义控件“设计器模式”

最近在MSDN上看到一个人提问如何把自定义的Label拖拽到WinForm上的时候,AutoSize自动设置成False。他当时给出的方法是:

[C#]

class MyLabel : Label
{
public MyLabel()
{
AutoSize = false;
}
}

[VB.NET]

Class MyLabel
Inherits Label
Public Sub New()
AutoSize = False
End Sub
End Class

很简单,思路似乎也正确——因为MyLabel一旦被初始化之后,构造函数应该立即被执行,从而把AutoSize设置成False。可惜的是,这种做法当你使用手动编码动态加载的时候毫无问题——

[C#]

 private void Form1_Load(object sender, EventArgs e)
{
Controls.Add(new MyLabel());
}

[VB.NET]

Private Sub Form1_Load(sender As Object, e As EventArgs)
Controls.Add(New MyLabel())
End Sub

但是如果是拖拽式加载就会出现问题——当控件拖拽到WinForm上去的时候,实际上相当于做了一个初始化控件的操作,这个代码不是直接生成到Form_Load中,而是到了一个私有的函数InitializeComponent(一个专门用于初始化全部窗体上函数以及窗体自身UI设计时候的大杂烩)。同时还默认为Label生成了AutoSize=True。这样一来,Form一旦启动,先设置AutoSize=True,接着又把它设置成了False。以下是InitializeComponent完成代码:

[C#]

private void InitializeComponent()
{
this.myLabel1 = new WinFormCSharp.MyLabel();
this.SuspendLayout();
//
// myLabel1
//
this.myLabel1.AutoSize=true;
this.myLabel1.Location = new System.Drawing.Point(108, 160);
this.myLabel1.Name = "myLabel1";
this.myLabel1.Size = new System.Drawing.Size(53, 12);
this.myLabel1.TabIndex = 0;
this.myLabel1.Text = "myLabel1";
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(284, 262);
this.Controls.Add(this.myLabel1);
this.Name = "Form1";
this.Text = "Form1";
this.Load += new System.EventHandler(this.Form1_Load);
this.ResumeLayout(false);
}

[VB.NET]

Private Sub InitializeComponent()
Me.myLabel1 = New WinFormCSharp.MyLabel()
Me.SuspendLayout()
'
' myLabel1
'
Me.myLabel1.AutoSize = True
Me.myLabel1.Location = New System.Drawing.Point(108, 160)
Me.myLabel1.Name = "myLabel1"
Me.myLabel1.Size = New System.Drawing.Size(53, 12)
Me.myLabel1.TabIndex = 0
Me.myLabel1.Text = "myLabel1"
'
' Form1
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(6F, 12F)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.ClientSize = New System.Drawing.Size(284, 262)
Me.Controls.Add(Me.myLabel1)
Me.Name = "Form1"
Me.Text = "Form1"
AddHandler Me.Load, AddressOf Me.Form1_Load)
Me.ResumeLayout(False)
End Sub

那么如何处理呢?有几种办法:

一、重写InitLayout方法,该方法MSDN上有明确表示——在加载到容器中的瞬间发生(包括从ToolBox)中拖拽到WinForm上的时候(因为已经进入容器)。此时把AutoSize设置成False即可,参考代码如下:

[C#]

class MyLabel : Label
{
protected override void InitLayout()
{
base.InitLayout();
AutoSize = false;
}
}

[VB.NET]

Class MyLabel
Inherits Label
Protected Overrides Sub InitLayout()
MyBase.InitLayout()
AutoSize = False
End Sub
End Class

二、判断是否是“设计模式”,Label继承自Control,而Control有一个属性叫做"DesignMode"。因此你可以重写AutoSize,然后判断是否是设计模式(不是的话才允许赋值,这样的话默认返回是false),参考代码:

[C#]

class MyLabel : Label
{
public override bool AutoSize
{
get
{
return base.AutoSize;
}
set
{
if (!DesignMode)
{
base.AutoSize = value;
}
}
}
}

[VB.NET]

Class MyLabel
Inherits Label
Public Overrides Property AutoSize() As Boolean
Get
Return MyBase.AutoSize
End Get
Set
If Not DesignMode Then
MyBase.AutoSize = value
End If
End Set
End Property
End Class
posted @ 2012-03-16 20:11  Serviceboy  阅读(2263)  评论(1编辑  收藏  举报