问题描述
我认为我的愚蠢问题有一个简单的解决方案,但我今天无法解决.
I think there is a simple solution for my stupid question but I just can't solve it today.
我有一个用户控件,它本身有一个 MaskedTextBox
控件.我还公开了它的一些属性供用户修改.
I have a User Control that has a MaskedTextBox
Control in itself. I have also exposed a few of its properties for the user to modify.
其中一个属性是 Mask
属性,我想公开它,以便能够使用预定义的值启动编辑器,就像在普通的 MaskedTextBox 控件中一样.
One of these properties is Mask
property which I want to expose with the ability of starting an editor with predefined values like in a normal MaskedTextBox control.
所以我创建了一个公共属性 InputMask 并设置了所有内容以便它可以工作,但是在显示编辑器后,我得到一个包含此错误的错误对话框:
So I created a public property InputMask and set up everything so that it can work but after showing the editor, I get an error dialog which contains this error:
对象引用未设置为对象的实例
Object reference not set to an instance of an object
如果我不使用编辑器并复制掩码或通过代码设置它,则可以正常工作.
If i don't use editor and copy a mask or set it trough code works without problems.
这是一个代码示例:
...
MaskedTextBox maskedtextbox;
myUserControl()
{
...
maskedtextbox = new MaskedTextBox(){
some stuff...
};
}
[DefaultValue("")]
[Editor("System.Windows.Forms.Design.MaskPropertyEditor, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(UITypeEditor))]
[Localizable(true)]
[MergableProperty(false)]
[RefreshProperties(RefreshProperties.Repaint)]
public string InputMask
{
get { return this.maskedtextbox.Mask; }
set { this.maskedtextbox.Mask = value; }
}
推荐答案
一般情况下注册UI类型编辑器就足够了,不需要额外做任何事情.但是在 MaskPropertyEditor
的情况下,编辑属性时,编辑器期望属性属于 MaskedTextBox
并转换 ITypeDescriptorContext.Instance
到 MaskedTextBox
并且由于我们的编辑 Mask
属性属于我们的 UserControl
这不是蒙面文本框,会抛出空引用异常.
In normal cases it's enough to register UI type editor and you don't need to do anything extra. But in MaskPropertyEditor
case, when editing the property, the editor expect the the property belong to a MaskedTextBox
and converts ITypeDescriptorContext.Instance
to MaskedTextBox
and since our editing Mask
property belongs to our UserControl
which is not a masked text box, a null reference exception will throw.
要解决这个问题,你需要创建一个自定义的UITypeEditor
并覆盖EditValue
并编辑私有MaskedTextBox的
字段.为此,我们需要创建一个包含 Mask
属性MaskedTextBox
的 ITypeDescriptorContext
实例并将其传递给编辑器的 EditValue
方法.
To solve the problem, you need to create a custom UITypeEditor
and override EditValue
and edit Mask
property of the private MaskedTextBox
field. To do so, we need to create an instance of ITypeDescriptorContext
containing the MaskedTextBox
and pass it to EditValue
method of the editor.
这里是实现.
用户控制
public partial class UserControl1 : UserControl
{
MaskedTextBox maskedTextBox;
public UserControl1()
{
InitializeComponent();
maskedTextBox = new MaskedTextBox();
}
[Editor(typeof(MaskEditor), typeof(UITypeEditor))]
public string Mask
{
get { return maskedTextBox.Mask; }
set { maskedTextBox.Mask = value; }
}
}
编辑器
public class MaskEditor : UITypeEditor
{
public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
{
return UITypeEditorEditStyle.Modal;
}
public override object EditValue(ITypeDescriptorContext context,
IServiceProvider provider, object value)
{
var field = context.Instance.GetType().GetField("maskedTextBox",
System.Reflection.BindingFlags.NonPublic |
System.Reflection.BindingFlags.Instance);
var maskedTextBox = (MaskedTextBox)field.GetValue(context.Instance);
var maskProperty = TypeDescriptor.GetProperties(maskedTextBox)["Mask"];
var tdc = new TypeDescriptionContext(maskedTextBox, maskProperty);
var editor = (UITypeEditor)maskProperty.GetEditor(typeof(UITypeEditor));
return editor.EditValue(tdc, provider, value);
}
}
ITypeDescriptionContext 实现
public class TypeDescriptionContext : ITypeDescriptorContext
{
private Control editingObject;
private PropertyDescriptor editingProperty;
public TypeDescriptionContext(Control obj, PropertyDescriptor property)
{
editingObject = obj;
editingProperty = property;
}
public IContainer Container
{
get { return editingObject.Container; }
}
public object Instance
{
get { return editingObject; }
}
public void OnComponentChanged()
{
}
public bool OnComponentChanging()
{
return true;
}
public PropertyDescriptor PropertyDescriptor
{
get { return editingProperty; }
}
public object GetService(Type serviceType)
{
return editingObject.Site.GetService(serviceType);
}
}
可能需要重新加载项目,Visual Studio 才能识别新的 UITypeEditor
The project may need to be reloaded before Visual Studio can recognize the new UITypeEditor
这篇关于如何为用户控件中的公开属性使用内置编辑器 - 掩码属性编辑器问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!