簡體   English   中英

如何使用內置 UITypeEditors 的控件?

[英]How to use controls from built-in UITypeEditors?

我想在我的下拉 UITypeEditor 中使用“選擇資源”對話框來自定義結構屬性。 我已經有TestEditorControl:UserControl ,其中包含一個帶有Click事件處理程序的button1

btn.Click+=(s,a)=>{
    OpenFileDialog oDlg = new OpenFileDialog();
    if (oDlg.ShowDialog() == DialogResult.OK)
    {
        ...
    }
}

如何用“選擇資源”對話框替換“OpenFileDialog”? 我嘗試了這段代碼(基於Visual Studio“選擇資源”對話框替換):

private Form resDialog;
public TestEditorControl()
{
    InitializeComponent();
    var property = TypeDescriptor.GetProperties(button1)["Image"];
    var resourceEditorSwitch = property.GetEditor(typeof(UITypeEditor)) as UITypeEditor;
    var editorToUseField = resourceEditorSwitch.GetType().GetProperty("EditorToUse",
        System.Reflection.BindingFlags.Instance |
        System.Reflection.BindingFlags.NonPublic);
    var editorToUse = editorToUseField.GetValue(resourceEditorSwitch);

    //System.NullReferenceException     (editorToUseField == null)

    var resourcePickerUIField = editorToUse.GetType().GetField("resourcePickerUI",
        System.Reflection.BindingFlags.Instance |
        System.Reflection.BindingFlags.NonPublic);
    var resDialog= (Form)Activator.CreateInstance(resourcePickerUIField.FieldType);
}

btn.Click+=(s,a)=>{
    if (resDialog.ShowDialog() == DialogResult.OK)
    {
        ...
    }
}

要顯示屬性的編輯器,您需要獲取屬性的UITypeEditor並調用其EditValue

var editor = (UITypeEditor)propertyDescriptor.GetEditor(typeof(UITypeEditor));
var editedValue = editor.EditValue(context, provider, propertyValue);

您需要傳遞給方法的值取決於代碼的上下文,除了本文中的示例之外,我還在本文底部分享了一些其他鏈接。

示例 - 顯示嵌套屬性的 Select 圖像對話框

在這個例子中,我創建了一個MyTestControl ,它有一個名為MyTestProperty的屬性,它是MyTestClass類型,它有一個Image類型的MyTestImage屬性。 我將顯示MyTestPropertyUITypeEditor和編輯器內的按鈕,該按鈕顯示 select 圖像對話框並更改圖像屬性:

在此處輸入圖像描述

控制

using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing;
using System.Drawing.Design;
using System.Windows.Forms;
using System.Windows.Forms.Design;
public class MyTestControl : Control
{
    [Editor(typeof(MyTestClassEditor), typeof(UITypeEditor))]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    public MyTestClass MyTestProperty { get; set; } = new MyTestClass();

    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);
        if (MyTestProperty != null &&
            MyTestProperty.MyTestImageProperty != null)
            e.Graphics.DrawImage(MyTestProperty.MyTestImageProperty,
                ClientRectangle.Location);
    }
}
public class MyTestClass
{
    public Image MyTestImageProperty { get; set; }
}

UITypeEditor

public class MyTestClassEditor : UITypeEditor
{
    public override UITypeEditorEditStyle GetEditStyle(
        ITypeDescriptorContext context)
    {
        return UITypeEditorEditStyle.DropDown;
    }
    public override object EditValue(ITypeDescriptorContext context, 
        IServiceProvider provider, object value)
    {
        var svc = (IWindowsFormsEditorService)provider
            .GetService(typeof(IWindowsFormsEditorService));
        var propertyToEdit = TypeDescriptor.GetProperties(value)
            [nameof(MyTestClass.MyTestImageProperty)];
        var ctx = new TypeDescriptionContext(
            (Control)context.Instance, provider, value, propertyToEdit);
        var editorControl = new MyTestClassEditorControl(svc, ctx, provider);
        svc.DropDownControl(editorControl);
        return editorControl.Result;
    }
}

編輯器控制

public class MyTestClassEditorControl : Control
{
    public Object Result { get; private set; }
    public MyTestClassEditorControl(IWindowsFormsEditorService service,
        ITypeDescriptorContext context, IServiceProvider provider) 
    {
        Result = context.Instance;
        var button = new Button() { Text = "Choose Image",  AutoSize = true };
        button.Click += (sender, e) =>
        {
            try
            {
                var imageProp = context.PropertyDescriptor;
                var imageValue = imageProp.GetValue(context.Instance);
                var editor = (UITypeEditor)imageProp
                    .GetEditor(typeof(UITypeEditor));
                var selectedImage = editor.EditValue(
                    context, provider, imageValue);
                imageProp.SetValue(context.Instance, selectedImage);
                context.OnComponentChanging();
                context.OnComponentChanged();
                service.CloseDropDown();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        };
        this.Controls.Add(button);
        this.Height = 100;
    }
}

類型描述上下文

public class TypeDescriptionContext : ITypeDescriptorContext
{
    Control control;
    IServiceProvider provider;
    object instannce;
    PropertyDescriptor property;
    public TypeDescriptionContext(Control control,
        IServiceProvider provider, object instannce,
        PropertyDescriptor property)
    {
        this.control = control;
        this.provider = provider;
        this.instannce = instannce;
        this.property = property;
    }
    public IContainer Container => control.Site?.Container;
    public object Instance => instannce;
    public void OnComponentChanged() =>
        GetService<IComponentChangeService>()
        ?.OnComponentChanged(control, null, null, null);
    public bool OnComponentChanging() => true;
    public PropertyDescriptor PropertyDescriptor => property;
    public object GetService(Type type) => provider?.GetService(type);
    public T GetService<T>() => (T)this.GetService(typeof(T));
}

更多示例

您可能需要查看以下帖子以獲取更多示例:

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM