I think there is a simple solution for my stupid question but I just can't solve it today.
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.
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.
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.
Here is a code sample:
...
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; }
}
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.
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.
Here is the implementations.
UserControl
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; }
}
}
Editor
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 Implementation
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);
}
}