如果编辑器应具有初始化行为,则重写 UITypeEditor 构造函数方法。
下面是我写的checkbox属性下拉框的例子:
1. 首先建立一个usercontrol
以下是源码 :
public partial class PropertyFundStatus : UserControl
{
private bool canceling;
private FundStatus _oldfundstatus;
private FundStatus _newfundstatus;
public PropertyFundStatus(FundStatus fundstatus)
{
_oldfundstatus = fundstatus;
_newfundstatus = fundstatus;
InitializeComponent();
}
public FundStatus FundStatus
{
get { return _newfundstatus; }
}
protected override bool ProcessDialogKey(Keys keyData) //重写键盘接收处理ESC
{
if (keyData == Keys.Escape)
{
_oldfundstatus = _newfundstatus;
canceling = true;
}
return base.ProcessDialogKey(keyData);
}
// 离开控件保存值
private void PropertyFundStatus_Leave(object sender, EventArgs e)
{
if (!canceling)
{
//保存值
if (hscb_normal.Checked)
{
_newfundstatus.Normal = true;
}
else
{
_newfundstatus.Normal = false;
}
if (hscb_Frozen.Checked)
{
_newfundstatus.Frozen = true;
}
else
{
_newfundstatus.Frozen = false;
}
if (hscb_Cancel.Checked)
{
_newfundstatus.Cancel = true;
}
else
{
_newfundstatus.Cancel = false;
}
}
}
//加载属性控件的时候赋值
private void PropertyFundStatus_Load(object sender, EventArgs e)
{
//赋值
hscb_normal.CheckState = _oldfundstatus.Normal ? CheckState.Checked : CheckState.Unchecked;
hscb_Frozen.CheckState = _oldfundstatus.Frozen ? CheckState.Checked : CheckState.Unchecked;
hscb_Cancel.CheckState = _oldfundstatus.Cancel ? CheckState.Checked : CheckState.Unchecked;
}
}
2. 这个自定义控件三个选项值保存在FundStatus类中
public class FundStatus
{
///
/// 正常
///
private bool _normal = false;
///
/// 注销
///
private bool _cancel = false;
///
/// 冻结
///
private bool _frozen = false;
public bool Normal
{
get { return _normal; }
set { _normal = value; }
}
public bool Cancel
{
get { return _cancel; }
set { _cancel = value; }
}
public bool Frozen
{
get { return _frozen; }
set { _frozen = value; }
}
}
3. 说了这些还没有到说到正题,下面来介绍自定义控件的属性
自定义控件[ComboFund]属性
[ Editor(typeof (FundStatusEditor), typeof (UITypeEditor)), //属性编辑器接口
TypeConverter(typeof (FundStatusConverter)),
//值转化器
DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
//序列化内容保存设置的值
public FundStatus FundStatus
{
get { return this._fundType; }
set
{
if (this._fundType != value)
{
this._fundType = value;
this.Reset();
}
}
}
自定义控件的构造函数里面需要实例化这个Fundstatus
_fundType = new FundStatus(); // 这个比较重要,最开始的时候这个忘记实例化了,调了半天。
4.注意到TypeConverter(typeof (FundStatusConverter))这个特性
public class FundStatusConverter : TypeConverter
{
///
///
是否能用string转换到fundstatus类型。
///
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
if (sourceType == typeof(String)) return true;
//这里也可以是其它类型的,可以参考后面的链接里面有介绍
return base.CanConvertFrom(context, sourceType);
}
///
/// 能否从fundstatus转换到string
///
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
if (destinationType == typeof(
FundStatus
)) return true;
// if (destinationType == typeof(InstanceDescriptor)) return true;
return base.CanConvertTo(context, destinationType);
}
///
/// 从string转到
Fundstatus
类型。在Property窗口中显示为string类型。
///
public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
{
String result = "";
if (value == null) return result;
if (destinationType == typeof(String))
{
//这里处理选择后在属性框里面显示的值
FundStatus
scope = (
FundStatus
)value;
if (scope.Normal)
{
if (result.Length > 0)
result += ",normal";
else
result += "normal";
}
else
result = result.Replace("normal", "").Replace(",normal", "");
if (scope.Cancel)
{
if (result.Length > 0)
result += ",cancel";
else
result += "cancel";
}
else
result = result.Replace("cancel", "").Replace(",cancel", "");
if (scope.Frozen)
{
if (result.Length > 0)
result += ",frozen";
else
result += "frozen";
}
else
result = result.Replace("frozen", "").Replace(",frozen", "");
return result;
}
if (destinationType == typeof(InstanceDescriptor))
{
ConstructorInfo ci = typeof(FundStatus).GetConstructor(new Type[] { typeof(bool), typeof(bool),typeof(bool) });
FundStatus scope = (FundStatus)value;
return new InstanceDescriptor(ci, new object[] { scope.Cancel, scope.Frozen,scope.Normal });
}
return base.ConvertTo(context, culture, value, destinationType);
}
///
/// 从
fundstatus转换为string
///
public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
{
if (value == null || value.ToString().Length == 0) return new FundStatus();
if (value is string)
{
//String[] v = ((String)value).Split(',');
string tempvalue = (string) value;
FundStatus csf = new
FundStatus();
csf.Cancel = tempvalue.Contains("cancel");
csf.Frozen = tempvalue.Contains("frozen");
csf.Normal = tempvalue.Contains("normal");
return csf;
}
return base.ConvertFrom(context, culture, value);
}
5. 说到这里最重要的东西还没有讲,继承基类UITypeEditor的FundStatusEditor
public class FundStatusEditor : UITypeEditor
{
[System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand)]
public override System.Drawing.Design.UITypeEditorEditStyle GetEditStyle(System.ComponentModel.ITypeDescriptorContext context)
{
if (context != null && context.Instance != null)
{
//这里设置下拉模式,还有弹出框的模式
return UITypeEditorEditStyle.DropDown;
}
return base.GetEditStyle(context);
}
[System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand)]
public override object EditValue(System.ComponentModel.ITypeDescriptorContext context,
System.IServiceProvider provider, object value)
{
IWindowsFormsEditorService editorService = null;
if (context != null && context.Instance != null && provider != null)
{
editorService =(IWindowsFormsEditorService)provider.GetService(typeof (IWindowsFormsEditorService));
if (editorService != null)
{
//
ComboFund 自定义控件
ComboFund control = (ComboFund)context.Instance;
PropertyFundStatus pfs = new PropertyFundStatus(control.FundStatus);
editorService.DropDownControl(pfs);
value = pfs.FundStatus;
return value;
}
}
return value;
}
}
6.这些搞完后如下图,这个就是我们要的属性选择,当然我们还可以做成弹出框的样式还有自己想怎么定义样式就怎么定义,非常方便。
参考资料:
http://msdn.microsoft.com/zh-cn/library/vstudio/system.drawing.design.uitypeeditor.aspx
http://www.cnblogs.com/mapserver/archive/2006/03/08/345244.html
http://www.cnblogs.com/guanjinke/archive/2006/12/19/597260.html