簡體   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