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);
}
}
The project may need to be reloaded before Visual Studio can recognize the new UITypeEditor
MaskPropertyEditor
case, when editing the property, the editor expect the the property belong to aMaskedTextBox
. So you should exactly edit theMask
property of theMaskedTextBox
. – Galvan