繁体   English   中英

如何创建打开表单的自定义通用 PropertyGrid 编辑器项目?

[英]How to create custom generic PropertyGrid editor item which opens a form?

我有一个自定义的通用表单

 public partial class MyTestForm1 : MyBrowseForm<CONTACTS_BASE>

其中 CONTACTS_BASE 是一个 EntityFramework 实体。

在父类上,我想要一个属性,这样当我在设计器时从属性网格中单击它时,它会打开一个表单,在该表单上我想要一个组合框,其中包含 CONTACTS_BASE 实体上的字段。

我发现这篇文章Marc Gravell 的回答帮助我在设计时单击属性时打开了一个新表单,并且我还使用 CONTACTS_BASE 字段填充了 ComboBox。 但要在表单加载事件上执行此操作,我调用了我所做的函数,该函数返回字段列表并将其设置为 ComboBox 的数据源。

comboBox1.DataSource = EntityBase.BaseGetTableFieldList2<CONTACTS_BASE>();

在此处输入图片说明

但是我想完成的是使这个通用

所以我想做的是这样的事情来填充 ComboBox。

public partial class BdEditorForm <TParentEntity>:Form where TParentEntity:class
{
    private void BdEditorForm_Load(object sender, EventArgs e)
    {       
     comboBox1.DataSource = EntityBase.BaseGetTableFieldList2<TParentEntity>();
    }
}

这样的事情可能吗? 因为当我尝试这样做时,我也需要使 TypeEditor 通用,然后在为我创建的属性赋予属性时

[Editor(typeof(BdFormTypeEditor<TParentEntity>), typeof(UITypeEditor))]
[TypeConverter(typeof(ExpandableObjectConverter))]

它说: 在此处输入图片说明

任何帮助表示感谢感谢和抱歉我的英语不好

简答

要知道如何解决这个问题,您需要知道EditValue方法有一个context参数,它是ITypeDescriptorContext类型,并且有一个Instance属性,它是您正在编辑的属性的所有者对象。 拥有所有者(表单),我们知道表单的类型,因此我们知道通用参数类型,因此我们可以创建我们的通用编辑器表单。

分步示例

以上事实是答案的关键点,但要解决问题,您还需要应用一些其他技巧。 例如,您应该获得一个泛型类型并使用反射创建它的一个实例。

这里我放了一个项目,其中包含示例的整个源代码:

以下是示例的步骤,该示例创建自定义模型 UI 类型编辑器,以在您编辑从MyBaseForm<T>派生的表单的特定属性时显示T的属性列表。

通用基础表格

它是包含SomeProperty其他表单的基本表单,您要使用自定义编辑器编辑该属性。

MyGenericType属性添加到返回typeof(T)的类中,该类是表单的泛型类型:

public partial class MyBaseForm<T> : Form
{
    public MyBaseForm()
    {
        InitializeComponent();
    }

    [Editor(typeof(MyUITypeEditor), typeof(UITypeEditor))]
    public string SomeProperty { get; set; }

    [Browsable(false)]
    public Type MyGenericType { get { return typeof(T); } }
}

派生形式

它是派生自MyBaseForm<T>的示例派生形式。 我们将编辑此类实例的SomeProperty

public partial class MyDerivedForm : MyBaseForm<MySampleModel>
{
    public MyDerivedForm()
    {
        InitializeComponent();
    }
}

示例模型

这是一个示例模型,我们将在自定义编辑器窗口中显示其属性。

public class MySampleModel
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Price { get; set; }
}

编辑表格

这是UITypeEditor将显示的表单。 在表单中,我们用通用参数的字段名称填充comoBox1

public partial class MyEditorForm<T> : Form
{
    public MyEditorForm()
    {
        InitializeComponent();
        this.StartPosition = FormStartPosition.CenterScreen;
        var list = ListBindingHelper.GetListItemProperties(typeof(T))
            .Cast<PropertyDescriptor>()
            .Select(x => new { Text = x.Name, Value = x }).ToList();
        this.comboBox1.DataSource = list;
        this.comboBox1.DisplayMember = "Text";
        this.comboBox1.ValueMember = "Value";
    }
    public string SelectedProperty
    {
        get
        {
            return comboBox1.GetItemText(comboBox1.SelectedItem);
        }
    }
    private void button1_Click(object sender, EventArgs e)
    {
        this.DialogResult = DialogResult.OK;
    }
}

UI 类型编辑器

调用UITypeEditor EditValue方法时, context参数的类型为System.Windows.Forms.PropertyGridInternal.PropertyDescriptorGridEntry ,它有一个Component属性,其值是您正在编辑的表单的实例,因此我们知道表单的类型因此我们知道通用参数类型,因此我们可以创建我们的通用编辑器表单并使用它。

public class MyUITypeEditor : UITypeEditor
{
    public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
    {
        return UITypeEditorEditStyle.Modal;
    }
    public override object EditValue(ITypeDescriptorContext context,
        IServiceProvider provider, object value)
    {
        var svc = provider.GetService(typeof(IWindowsFormsEditorService))
            as IWindowsFormsEditorService;
        var myGenericTypeProperty = context.Instance.GetType()
            .GetProperty("MyGenericType");
        var genericArgument = (Type)myGenericTypeProperty.GetValue(context.Instance);
        var editorFormType = typeof(MyEditorForm<>);
        var genericArguments = new[] { genericArgument };
        var editorFormInstance = editorFormType.MakeGenericType(genericArguments);
        if (svc != null)
        {
            using (var f = (Form)Activator.CreateInstance(editorFormInstance))
                if (svc.ShowDialog(f) == DialogResult.OK)
                    return ((dynamic)f).SelectedProperty;
        }
        else
        {
            using (var f = (Form)Activator.CreateInstance(editorFormInstance))
                if (f.ShowDialog() == DialogResult.OK)
                    return ((dynamic)f).SelectedProperty;
        }
        return base.EditValue(context, provider, value);
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM