【问题标题】:How to use built-in editors for a exposed properties in User Controls - Mask Property Editor Issue如何为用户控件中的公开属性使用内置编辑器 - 掩码属性编辑器问题
【发布时间】:2016-03-30 11:39:26
【问题描述】:

我认为我的愚蠢问题有一个简单的解决方案,但我今天无法解决。

我有一个用户控件,它本身有一个MaskedTextBox 控件。我还公开了它的一些属性供用户修改。

其中一个属性是Mask 属性,我想公开它,它可以使用预定义值启动编辑器,就像在普通的 MaskedTextBox 控件中一样。

所以我创建了一个公共属性 InputMask 并设置了所有内容以便它可以工作,但是在显示编辑器后,我得到一个包含此错误的错误对话框:

对象引用未设置为对象的实例

如果我不使用编辑器并复制掩码或通过代码设置它,则可以正常工作。

这是一个代码示例:

...
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。因此,您应该准确编辑 MaskedTextBoxMask 属性。

标签: c# winforms user-controls windows-forms-designer maskedtextbox


【解决方案1】:

一般情况下,注册 UI 类型编辑器就足够了,你不需要做任何额外的事情。但是在MaskPropertyEditor 的情况下,编辑属性时,编辑器期望属性属于MaskedTextBox 并将ITypeDescriptorContext.Instance 转换为MaskedTextBox,并且由于我们编辑Mask 属性属于我们的UserControl,这不是一个被屏蔽的文本框,会抛出一个空引用异常。

要解决此问题,您需要创建自定义UITypeEditor 并覆盖EditValue 并编辑私有Mask 属性MaskedTextBox 字段。为此,我们需要创建一个包含MaskedTextBoxITypeDescriptorContext 实例并将其传递给编辑器的EditValue 方法。

这里是实现。

用户控制

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

【讨论】:

  • 非常感谢。它工作得很好。我更像是一个 Photoshop 人员(超过 10 年的设计师)而不是 C# 开发人员,但感谢你帮助我几次,我为 Windows 窗体应用程序设计并实现了一个漂亮的 UI。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-01-06
  • 1970-01-01
  • 2018-02-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-29
相关资源
最近更新 更多