Is there any way to use a CollectionEditor outside

2019-04-02 00:25发布

问题:

I'm replacing my property grid with something that will allow me to customize my UI a bit better. I placed a button on my form that I hope when clicked would pop up a CollectionEditor and allow me to modify my code. When I was using the PropertyGrid, all I needed to do was add some attributes to the property pointing to my CollectionEditor and it worked. But how do I invoke the CollectionEditor manually? Thanks!

回答1:

Found the answer here: http://www.devnewsgroups.net/windowsforms/t11948-collectioneditor.aspx

Just in case the site linked above goes away some day, here's the gist of it. The code is verbatim from the link above, however; the comments are mine.

Assume you have a form with a ListBox and a button. If you wanted to edit the items in the ListBox using the CollectionEditor, you would do the following in your EventHandler:

private void button1_Click(object sender, System.EventArgs e)
{
    //listBox1 is the object containing the collection.  Remember, if the collection
    //belongs to the class you're editing, you can use this
    //Items is the name of the property that is the collection you wish to edit.
    PropertyDescriptor pd = TypeDescriptor.GetProperties(listBox1)["Items"];
    UITypeEditor editor = (UITypeEditor)pd.GetEditor(typeof(UITypeEditor));
    RuntimeServiceProvider serviceProvider = new RuntimeServiceProvider();
    editor.EditValue(serviceProvider, serviceProvider, listBox1.Items);
}

Now the next thing you need to do is to create the RuntimeServiceProvider(). This is the code the poster in the link above wrote to implement this:

public class RuntimeServiceProvider : IServiceProvider, ITypeDescriptorContext
{
    #region IServiceProvider Members

    object IServiceProvider.GetService(Type serviceType)
    {
        if (serviceType == typeof(IWindowsFormsEditorService))
        {
            return new WindowsFormsEditorService();
        }

        return null;
    }

    class WindowsFormsEditorService : IWindowsFormsEditorService
    {
        #region IWindowsFormsEditorService Members

        public void DropDownControl(Control control)
        {
        }

        public void CloseDropDown()
        {
        }

        public System.Windows.Forms.DialogResult ShowDialog(Form dialog)
        {
            return dialog.ShowDialog();
        }

        #endregion
    }

    #endregion

    #region ITypeDescriptorContext Members

    public void OnComponentChanged()
    {
    }

    public IContainer Container
    {
        get { return null; }
    }

    public bool OnComponentChanging()
    {
        return true; // true to keep changes, otherwise false
    }

    public object Instance
    {
        get { return null; }
    }

    public PropertyDescriptor PropertyDescriptor
    {
        get { return null; }
    }

    #endregion
}


回答2:

Since I can't comment i'll post this here:

You can get the DialogResult by adding a Click event on the okButton of the CollectionEditor in WindowsFormsEditorService.ShowDialog

public System.Windows.Forms.DialogResult ShowDialog(Form dialog)
{
    ((System.Windows.Forms.Button)dialog.Controls.Find("okButton", true)[0]).Click += WindowsFormsEditorService_Click;
    return dialog.ShowDialog();
}

...

private void WindowsFormsEditorService_Click(object sender, EventArgs e)
{
    dr = DialogResult.OK;
}