WinForm控件開發(fā)總結(jié)(十)-----為屬性設(shè)置默認值
本系列的前面幾篇文章講解了如何來定義屬性以及更有效的編輯屬性,接下來我要講一下控件屬性的默認值。如果我們希望自己開發(fā)的控件更易于被其它開發(fā)者使用,那么提供默認值是非常值得的。
如果你為屬性設(shè)定了默認值,那么當開發(fā)者修改了屬性的值,這個值在Property Explorer中將會以粗體顯示。VS為屬性提供一個上下文菜單,允許程序員使用控件把值重置為默認值。當VS進行控件的串行化時,他會判斷那些值不是默認值,只有不是默認值的屬性才會被串行化,所以為屬性提供默認值時可以大大減少串行化的屬性數(shù)目,提高效率。
那么VS怎么知道我們的屬性值不是默認值了呢?我們需要一種機制來通知VS默認值。實現(xiàn)這種機制有兩種方法:
對于簡單類型的屬性,比如Int32,Boolean等等這些Primitive類型,你可以在屬性的聲明前設(shè)置一個DefaultValueAttribute,在Attribute的構(gòu)造函數(shù)里傳入默認值。
對于復(fù)雜的類型,比如Font,Color,你不能夠直接將這些類型的值傳遞給Attibute的構(gòu)造函數(shù)。相反你應(yīng)該提供Reset<PropertyName> 和ShouldSerialize<PropertyName>方法,比如ResetBackgroundColor(),ShouldSerializeBackgroundColor()。VS能夠根據(jù)方法的名稱來識別這種方法,比如Reset<PropertyName>方法把重置為默認值,ShouldSerialize<PropertyName>方法檢查屬性是否是默認值。過去我們把它稱之為魔術(shù)命名法,應(yīng)該說是一種不好的編程習(xí)慣,可是現(xiàn)在微軟依然使用這種機制。我還是以前面幾篇文章使用的例子代碼。
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.ComponentModel;
using System.Drawing;
![]()
namespace CustomControlSample
{
public class FirstControl : Control
{
![]()
private String _displayText=”Hello World!”;
private Color _textColor=Color.Red;
![]()
public FirstControl()
{
![]()
}
![]()
// ContentAlignment is an enumeration defined in the System.Drawing
// namespace that specifies the alignment of content on a drawing
// surface.
private ContentAlignment alignmentValue = ContentAlignment.MiddleLeft;
![]()
[
Category("Alignment"),
Description("Specifies the alignment of text.")
]
public ContentAlignment TextAlignment
{
![]()
get
{
return alignmentValue;
}
set
{
alignmentValue = value;
![]()
// The Invalidate method invokes the OnPaint method described
// in step 3.
Invalidate();
}
}
![]()
![]()
[Browsable(true)]
[DefaultValue(“Hello World”)]
public String DisplayText
{
get
{
return _displayText;
}
set
{
_displayText =value;
Invalidate();
}
}
![]()
[Browsable(true)]
public Color TextColor
{
get
{
return _textColor;
}
set
{
_textColor=value;
Invalidate();
}
}
![]()
public void ResetTextColor()
{
TextColor=Color.Red;
}
![]()
public bool ShouldSerializeTextColor()
{
return TextColor!=Color.Red;
}
![]()
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
StringFormat style = new StringFormat();
style.Alignment = StringAlignment.Near;
switch (alignmentValue)
{
case ContentAlignment.MiddleLeft:
style.Alignment = StringAlignment.Near;
break;
case ContentAlignment.MiddleRight:
style.Alignment = StringAlignment.Far;
break;
case ContentAlignment.MiddleCenter:
style.Alignment = StringAlignment.Center;
break;
}
![]()
// Call the DrawString method of the System.Drawing class to write
// text. Text and ClientRectangle are properties inherited from
// Control.
e.Graphics.DrawString(
DisplayText,
Font,
new SolidBrush(TextColor),
ClientRectangle, style);
![]()
}
}
}
private String _displayText=”Hello World!”;
private Color _textColor=Color.Red;
如果你為屬性設(shè)定了默認值,那么當開發(fā)者修改了屬性的值,這個值在Property Explorer中將會以粗體顯示。VS為屬性提供一個上下文菜單,允許程序員使用控件把值重置為默認值。當VS進行控件的串行化時,他會判斷那些值不是默認值,只有不是默認值的屬性才會被串行化,所以為屬性提供默認值時可以大大減少串行化的屬性數(shù)目,提高效率。
那么VS怎么知道我們的屬性值不是默認值了呢?我們需要一種機制來通知VS默認值。實現(xiàn)這種機制有兩種方法:
對于簡單類型的屬性,比如Int32,Boolean等等這些Primitive類型,你可以在屬性的聲明前設(shè)置一個DefaultValueAttribute,在Attribute的構(gòu)造函數(shù)里傳入默認值。
對于復(fù)雜的類型,比如Font,Color,你不能夠直接將這些類型的值傳遞給Attibute的構(gòu)造函數(shù)。相反你應(yīng)該提供Reset<PropertyName> 和ShouldSerialize<PropertyName>方法,比如ResetBackgroundColor(),ShouldSerializeBackgroundColor()。VS能夠根據(jù)方法的名稱來識別這種方法,比如Reset<PropertyName>方法把重置為默認值,ShouldSerialize<PropertyName>方法檢查屬性是否是默認值。過去我們把它稱之為魔術(shù)命名法,應(yīng)該說是一種不好的編程習(xí)慣,可是現(xiàn)在微軟依然使用這種機制。我還是以前面幾篇文章使用的例子代碼。
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.ComponentModel;
using System.Drawing;
namespace CustomControlSample
{
public class FirstControl : Control
{
private String _displayText=”Hello World!”;
private Color _textColor=Color.Red;
public FirstControl()
{
}
// ContentAlignment is an enumeration defined in the System.Drawing
// namespace that specifies the alignment of content on a drawing
// surface.
private ContentAlignment alignmentValue = ContentAlignment.MiddleLeft;
[
Category("Alignment"),
Description("Specifies the alignment of text.")
]
public ContentAlignment TextAlignment
{
get
{
return alignmentValue;
}
set
{
alignmentValue = value;
// The Invalidate method invokes the OnPaint method described
// in step 3.
Invalidate();
}
}

[Browsable(true)]
[DefaultValue(“Hello World”)]
public String DisplayText
{
get
{
return _displayText;
}
set
{
_displayText =value;
Invalidate();
}
}
[Browsable(true)]
public Color TextColor
{
get
{
return _textColor;
}
set
{
_textColor=value;
Invalidate();
}
}
public void ResetTextColor()
{
TextColor=Color.Red;
}
public bool ShouldSerializeTextColor()
{
return TextColor!=Color.Red;
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
StringFormat style = new StringFormat();
style.Alignment = StringAlignment.Near;
switch (alignmentValue)
{
case ContentAlignment.MiddleLeft:
style.Alignment = StringAlignment.Near;
break;
case ContentAlignment.MiddleRight:
style.Alignment = StringAlignment.Far;
break;
case ContentAlignment.MiddleCenter:
style.Alignment = StringAlignment.Center;
break;
}
// Call the DrawString method of the System.Drawing class to write
// text. Text and ClientRectangle are properties inherited from
// Control.
e.Graphics.DrawString(
DisplayText,
Font,
new SolidBrush(TextColor),
ClientRectangle, style);
}
}
}
在上面的代碼中,我增加了兩個屬性,一個是DisplayText,這是一個簡單屬性,我們只需要在它的聲明前添加一個DefaultValue Attribute就可以了。另外一個是TextColor屬性,這個復(fù)雜類型的屬性,所以我們提供了ResetTextColor和ShouldSerializeTextColor來實現(xiàn)默認值。
默認值的實現(xiàn)就講完了,但是有一點不要忽視了,你設(shè)定了默認值,就應(yīng)該相應(yīng)的初始化這些屬性,比如我們例子中的代碼:
private String _displayText=”Hello World!”;
private Color _textColor=Color.Red;



浙公網(wǎng)安備 33010602011771號