Laden...

PropertyGrid: Editor auch per Klick öffnen

Erstellt von franz00 vor 12 Jahren Letzter Beitrag vor 9 Jahren 1.800 Views
F
franz00 Themenstarter:in
8 Beiträge seit 2011
vor 12 Jahren
PropertyGrid: Editor auch per Klick öffnen

Hallo,

im PropertyGrid kann ich ja mittels den StringCollectionEditor öffnen:

[Editor("System.Windows.Forms.Design.StringCollectionEditor, System.Design, Version=2.0.0.0, Culture=neutral,
      typeof(UITypeEditor))]

Ist es auch möglich diesen z.B. per Click-Event zu öffnen?

gruß Franz

2.921 Beiträge seit 2005
vor 9 Jahren

Ich habe diesen Code dazu im Internet gefunden, aber nicht ausprobiert:

EDIT: Ich weiss aber nicht mehr wo. Vielleicht reicht das ja schon aus?


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace StringCollectionEditorTest
{
    /// <include file="doc\StringCollectionEditor.uex" path="docs/doc[@for="StringCollectionEditor"]/*">
    /// <devdoc>
    ///      The StringCollectionEditor is a collection editor that is specifically
    ///      designed to edit collections containing strings.  The collection can be
    ///      of any type that can accept a string value; we just present a string-centric
    ///      dialog for the user.
    /// </devdoc>
    public class StringCollectionEditor : CollectionEditor
    {

        public StringCollectionEditor(Type type)
            : base(type)
        {
        }

        /// <include file="doc\StringCollectionEditor.uex" path="docs/doc[@for="StringCollectionEditor.CreateCollectionForm"]/*">
        /// <devdoc>
        ///      Creates a new form to show the current collection.  You may inherit
        ///      from CollectionForm to provide your own form.
        /// </devdoc>
        protected override CollectionForm CreateCollectionForm()
        {
            return new StringCollectionForm(this);
        }

        /// <include file="doc\StringCollectionEditor.uex" path="docs/doc[@for="StringCollectionEditor.HelpTopic"]/*">
        /// <devdoc>
        ///    <para>Gets the help topic to display for the dialog help button or pressing F1. Override to
        ///          display a different help topic.</para>
        /// </devdoc>
        protected override string HelpTopic
        {
            get
            {
                return "net.ComponentModel.StringCollectionEditor";
            }
        }

        /// <include file="doc\StringCollectionEditor.uex" path="docs/doc[@for="StringCollectionEditor.StringCollectionForm"]/*">
        /// <devdoc>
        ///     StringCollectionForm allows visible editing of a string array. Each line in
        ///     the edit box is an array entry.
        /// </devdoc>
        protected class StringCollectionForm : CollectionForm
        {

            private Label instruction;
            private TextBox textEntry;
            private Button okButton;
            private Button cancelButton;
            private TableLayoutPanel okCancelTableLayoutPanel;

            private StringCollectionEditor editor = null;

            /// <include file="doc\StringCollectionEditor.uex" path="docs/doc[@for="StringCollectionEditor.StringCollectionForm.StringCollectionForm"]/*">
            /// <devdoc>
            ///     Constructs a StringCollectionForm.
            /// </devdoc>
            public StringCollectionForm(CollectionEditor editor)
                : base(editor)
            {
                this.editor = (StringCollectionEditor)editor;
                InitializeComponent();
                HookEvents();
            }

            private void Edit1_keyDown(object sender, KeyEventArgs e)
            {
                if (e.KeyCode == Keys.Escape)
                {
                    cancelButton.PerformClick();
                    e.Handled = true;
                }
            }

            private void StringCollectionEditor_HelpButtonClicked(object sender, CancelEventArgs e)
            {
                e.Cancel = true;
                editor.ShowHelp();
            }

            private void Form_HelpRequested(object sender, HelpEventArgs e)
            {
                editor.ShowHelp();
            }

            private void HookEvents()
            {
                this.textEntry.KeyDown += new KeyEventHandler(this.Edit1_keyDown);
                this.okButton.Click += new EventHandler(this.OKButton_click);
                this.HelpButtonClicked += new System.ComponentModel.CancelEventHandler(this.StringCollectionEditor_HelpButtonClicked);
            }

            /// <include file="doc\StringCollectionEditor.uex" path="docs/doc[@for="StringCollectionEditor.StringCollectionForm.InitializeComponent"]/*">
            /// <devdoc>
            ///     NOTE: The following code is required by the form
            ///     designer.  It can be modified using the form editor.  Do not
            ///     modify it using the code editor.
            /// </devdoc>
            private void InitializeComponent()
            {
                System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(StringCollectionEditor));
                this.instruction = new System.Windows.Forms.Label();
                this.textEntry = new System.Windows.Forms.TextBox();
                this.okButton = new System.Windows.Forms.Button();
                this.cancelButton = new System.Windows.Forms.Button();
                this.okCancelTableLayoutPanel = new System.Windows.Forms.TableLayoutPanel();
                this.okCancelTableLayoutPanel.SuspendLayout();
                this.SuspendLayout();
                //
                // instruction
                //
                //resources.ApplyResources(this.instruction, "instruction");
                this.instruction.Margin = new System.Windows.Forms.Padding(3, 1, 3, 0);
                this.instruction.Name = "instruction";
                //
                // textEntry
                //
                this.textEntry.AcceptsTab = true;
                this.textEntry.AcceptsReturn = true;
                //resources.ApplyResources(this.textEntry, "textEntry");
                this.textEntry.Name = "textEntry";
                //
                // okButton
                //
                //resources.ApplyResources(this.okButton, "okButton");
                this.okButton.DialogResult = System.Windows.Forms.DialogResult.OK;
                this.okButton.Margin = new System.Windows.Forms.Padding(0, 0, 3, 0);
                this.okButton.Name = "okButton";
                //
                // cancelButton
                //
                //resources.ApplyResources(this.cancelButton, "cancelButton");
                this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
                this.cancelButton.Margin = new System.Windows.Forms.Padding(3, 0, 0, 0);
                this.cancelButton.Name = "cancelButton";
                //
                // okCancelTableLayoutPanel
                //
                //resources.ApplyResources(this.okCancelTableLayoutPanel, "okCancelTableLayoutPanel");
                this.okCancelTableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
                this.okCancelTableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
                this.okCancelTableLayoutPanel.Controls.Add(this.okButton, 0, 0);
                this.okCancelTableLayoutPanel.Controls.Add(this.cancelButton, 1, 0);
                this.okCancelTableLayoutPanel.Name = "okCancelTableLayoutPanel";
                this.okCancelTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle());
                //
                // StringCollectionEditor
                //
                //resources.ApplyResources(this, "$this");
                this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
                this.Controls.Add(this.okCancelTableLayoutPanel);
                this.Controls.Add(this.instruction);
                this.Controls.Add(this.textEntry);
                this.HelpButton = true;
                this.MaximizeBox = false;
                this.MinimizeBox = false;
                this.Name = "StringCollectionEditor";
                this.ShowIcon = false;
                this.ShowInTaskbar = false;
                this.okCancelTableLayoutPanel.ResumeLayout(false);
                this.okCancelTableLayoutPanel.PerformLayout();
                this.HelpRequested += new HelpEventHandler(this.Form_HelpRequested);
                this.ResumeLayout(false);
                this.PerformLayout();
            }

            /// <include file="doc\StringCollectionEditor.uex" path="docs/doc[@for="StringCollectionEditor.StringCollectionForm.OKButton_click"]/*">
            /// <devdoc>
            ///      Commits the changes to the editor.
            /// </devdoc>
            private void OKButton_click(object sender, EventArgs e)
            {
                char[] delims = new char[] { '\n' };
                char[] trims = new char[] { '\r' };

                string[] strings = textEntry.Text.Split(delims);
                object[] curItems = Items;

                int nItems = strings.Length;
                for (int i = 0; i < nItems; i++)
                {
                    strings[i] = strings[i].Trim(trims);
                }

                bool dirty = true;
                if (nItems == curItems.Length)
                {
                    int i;
                    for (i = 0; i < nItems; ++i)
                    {
                        if (!strings[i].Equals((string)curItems[i]))
                        {
                            break;
                        }
                    }

                    if (i == nItems)
                        dirty = false;
                }

                if (!dirty)
                {
                    DialogResult = DialogResult.Cancel;
                    return;
                }

                // ASURT #57372
                // If the final line is blank, we don't want to create an item from it
                //
                if (strings.Length > 0 && strings[strings.Length - 1].Length == 0)
                {
                    nItems--;
                }

                object[] values = new object[nItems];
                for (int i = 0; i < nItems; i++)
                {
                    values[i] = strings[i];
                }

                Items = values;
            }

            // <summary>
            //      This is called when the value property in the CollectionForm has changed.
            //      In it you should update your user interface to reflect the current value.
            // </summary>
            //
            protected override void OnEditValueChanged()
            {
                object[] items = Items;
                string text = string.Empty;

                for (int i = 0; i < items.Length; i++)
                {
                    if (items[i] is string)
                    {
                        text += (string)items[i];
                        if (i != items.Length - 1)
                        {
                            text += "\r\n";
                        }
                    }
                }

                textEntry.Text = text;
            }
        }
    }
}

dr4g0n76

Seit der Erkenntnis, dass der Mensch eine Nachricht ist, erweist sich seine körperliche Existenzform als überflüssig.

S
145 Beiträge seit 2013
vor 9 Jahren

Wie meinst du das mit beim Click ausführen?
Ich hab mal ein propertyGrid mittels C1FlexGrid selbst gebastelt, und dafür folgende Klassen angelegt:

Basisklasse für TypceConverter und UITypeEditor Handling

   /// <summary>
    /// Basisklasse für <see cref="PropertiesControlTypeConverter"/> und <see cref="PropertiesControlUITypeEditor"/>
    /// </summary>
    internal class PropertiesControlTypeDescriptorContext : ITypeDescriptorContext, IServiceProvider, IDisposable
    {
        protected PropertiesControlTypeDescriptorContext(object instance)
        {
            this.instance = instance;

            this.propertyDescriptors = new Dictionary<string, PropertyDescriptor>();
            foreach (PropertyDescriptor pd in TypeDescriptor.GetProperties(instance))
                propertyDescriptors.Add(pd.Name, pd);
        }

        /// <summary>
        /// wechselt akt. zu bearbeitende Eigenschaft
        /// </summary>
        /// <param name="propertyName">name der Eigenschaft die jetzt bearbeitet werden soll</param>
        internal void SetCurrentProperty(string propertyName)
        {
            propertyDescriptors.TryGetValue(propertyName, out propertyDescriptor);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                propertyDescriptors.Clear();

                propertyDescriptor = null;

                GC.SuppressFinalize(this);
            }
        }

        #region IDisposable Members

        /// <summary>
        /// Ressourcen freigeben
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
        }

        #endregion

        #region Statische Methoden

        /// <summary>
        /// liefert <see cref="PropertyDescriptor"/> für angegebene Eigenschaft
        /// </summary>
        /// <param name="instance">Instance aus der Eigenschaft kommt</param>
        /// <param name="propertyName">name der Eigenschaft für das <see cref="PropertyDescriptor"/> geliefert werden soll</param>
        /// <returns><see cref="PropertyDescriptor"/> wenn gefunden, sonst null</returns>
        protected static PropertyDescriptor GetPropertyDescriptor(object instance, string propertyName)
        {
            PropertyDescriptorCollection pdc = TypeDescriptor.GetProperties(instance);
            foreach (PropertyDescriptor pd in pdc)
            {
                if (string.Equals(propertyName, pd.Name, StringComparison.OrdinalIgnoreCase))
                    return pd;
            }
            return null;
        }

        #endregion

        #region ITypeDescriptorContext Members

        /// <summary>
        /// Gets the container representing this System.ComponentModel.TypeDescriptor  { get; }
        /// </summary>
        public IContainer Container
        {
            get { return null; }
        }

        /// <summary>
        /// Gets the object that is connected with this type descriptor request  { get; }
        /// </summary>
        public object Instance
        {
            get { return instance; }
        }

        /// <summary>
        /// Not Implemented
        /// </summary>
        public void OnComponentChanged()
        {
            throw new NotImplementedException("The method or operation is not implemented.");
        }

        /// <summary>
        /// Not Implemented
        /// </summary>
        /// <returns></returns>
        public bool OnComponentChanging()
        {
            throw new NotImplementedException("The method or operation is not implemented.");
        }

        /// <summary>
        /// Gets the System.ComponentModel.PropertyDescriptor that is associated with the given context item.  { get; }
        /// </summary>
        public PropertyDescriptor PropertyDescriptor
        {
            get { return propertyDescriptor; }
        }

        #endregion

        #region IServiceProvider Members

        /// <summary>
        /// Gets the service object of the specified type.
        /// </summary>
        /// <param name="serviceType">An object that specifies the type of service object to get.</param>
        /// <returns>A service object of type serviceType.-or- null if there is no service object of type serviceType.</returns>
        public virtual object GetService(Type serviceType)
        {
            if (serviceType == this.GetType())
                return this;

            return null;
        }

        #endregion

        private readonly object instance;
        private readonly Dictionary<string, PropertyDescriptor> propertyDescriptors;

        private PropertyDescriptor propertyDescriptor;
    }

Für UITypeEditor dann:

    internal class PropertiesControlUITypeEditor : PropertiesControlTypeDescriptorContext
    {
        public PropertiesControlUITypeEditor(Control parent, object instance)
            : base(instance)
        {
            this.uiTypeEditors = new Dictionary<string, UITypeEditor>();

            this.parent = parent;
        }

        /// <summary>
        /// liefert akt. <see cref="UITypeEditor"/>
        /// </summary>
        /// <returns></returns>
        private UITypeEditor GetEditor()
        {
            UITypeEditor uite;
            if (!uiTypeEditors.TryGetValue(PropertyDescriptor.Name, out uite))
            {
                uite = GetEditor(Instance, PropertyDescriptor);
                uiTypeEditors.Add(PropertyDescriptor.Name, uite);
            }

            return uite;
        }

        /// <summary>
        /// prüft ob akt. Eigenschaft (Eigenschaft wird gesetzt über <see cref="PropertiesControlTypeDescriptorContext.SetCurrentProperty"/>) <see cref="UITypeEditor"/> gesetzt hat oder dessen Type
        /// </summary>
        /// <param name="instance">Instance aus der Eigenschaft stammt</param>
        /// <param name="propertyName">name der zu prüfenden Eigenschaft</param>
        /// <returns>true - <see cref="UITypeEditor"/> ist gesetzt</returns>
        public bool HasEditor()
        {
            return (GetEditor() != null);
        }

        /// <summary>
        /// ruft Editor auf und liefert Wert für akt. Eigenschaft (Eigenschaft wird gesetzt über <see cref="PropertiesControlTypeDescriptorContext.SetCurrentProperty"/>)
        /// </summary>
        /// <returns>neue Eigenschaftenwert</returns>
        public object EditValue()
        {
            return GetEditor().EditValue(this, this, PropertyDescriptor.GetValue(Instance));
        }

        public override object GetService(Type serviceType)
        {
            object o = base.GetService(serviceType);
            if (o == null)
            {
                if (serviceType == typeof(System.Windows.Forms.Design.IWindowsFormsEditorService))
                {
                    if (windowsFormsEditorService == null)
                        windowsFormsEditorService = new WindowsFormsEditorService(parent);
                    return windowsFormsEditorService;
                }
            }
            return null;
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (windowsFormsEditorService != null)
                {
                    windowsFormsEditorService.Dispose();
                    windowsFormsEditorService = null;
                }

                uiTypeEditors.Clear();
            }

            base.Dispose(disposing);
        }

        #region Statische Methoden

        /// <summary>
        /// liefert <see cref="UITypeEditor"/> wenn gesetzt oder der Type der Eigenschaft dies gesetzt hat sonst null
        /// </summary>
        private static UITypeEditor GetEditor(object instance, PropertyDescriptor propertyDescriptor)
        {
            //EditorAttribute ea = null;
            //foreach (Attribute attr in propertyDescriptor.Attributes)
            //{
            //    if (attr is EditorAttribute)
            //    {
            //        ea = (EditorAttribute)attr;
            //        break;
            //    }
            //}

            //if (ea == null)
            //{
            //    object[] attrs = propertyDescriptor.PropertyType.GetCustomAttributes(typeof(EditorAttribute), true);
            //    if (attrs.GetLength(0) > 0)
            //        ea = (EditorAttribute)attrs[0];
            //}

            //if (ea != null)
            //    return (UITypeEditor)Activator.CreateInstance(Type.GetType(ea.EditorTypeName));

            //return TypeDescriptor.GetEditor(propertyDescriptor.PropertyType, typeof(UITypeEditor)) as UITypeEditor;

            return propertyDescriptor.GetEditor(typeof(UITypeEditor)) as UITypeEditor;
        }

        /// <summary>
        /// prüft ob angegebene Eigenschaft <see cref="TypeConverterAttribute"/> gesetzt hat oder dessen Type
        /// </summary>
        /// <param name="instance">Instance aus der Eigenschaft stammt</param>
        /// <param name="propertyName">name der zu prüfenden Eigenschaft</param>
        /// <returns>true - <see cref="TypeConverterAttribute"/> ist gesetzt</returns>
        public static bool HasEditor(object instance, string propertyName)
        {
            return (GetEditor(instance, GetPropertyDescriptor(instance, propertyName)) != null);
        }

        #endregion

        /// <summary>
        /// <see cref="IWindowsFormsEditorService"/> Klasse zum behandeln des <see cref="UITypeEditor"/>
        /// </summary>
        private class WindowsFormsEditorService : System.Windows.Forms.Design.IWindowsFormsEditorService, IDisposable
        {
            internal WindowsFormsEditorService(Control parent)
            {
                this.parent = parent;
            }

            #region IWindowsFormsEditorService Members

            public void CloseDropDown()
            {
                if (dropDownControl != null)
                {
                    dropDownControl.Leave -= new EventHandler(control_Leave);

                    parent.Controls.Remove(dropDownControl);
                    dropDownControl = null;
                }
            }

            public void DropDownControl(System.Windows.Forms.Control control)
            {
                CloseDropDown();

                dropDownControl = control;

                parent.Controls.Add(control);

                control.BringToFront();
                control.Location = parent.PointToClient(Control.MousePosition);

                System.Drawing.Rectangle recParent = new System.Drawing.Rectangle(parent.Location, parent.Size);
                System.Drawing.Rectangle recControl = new System.Drawing.Rectangle(control.Location, control.Size);

                while (recParent.Bottom<recControl.Bottom)
                    recControl.Y--;
                while (recParent.Right < recControl.Right)
                    recControl.X--;

                control.Location = recControl.Location;
                control.Focus();

                control.Leave += new EventHandler(control_Leave);

                while (true) //Schleife damit Control nicht sofort wieder verschwindet
                {
                    Application.DoEvents();
                    if (dropDownControl == null)
                        break;
                }
            }

            void control_Leave(object sender, EventArgs e)
            {
                CloseDropDown();
            }

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

            #endregion

            #region IDisposable Members

            public void Dispose()
            {
                CloseDropDown();
            }

            #endregion

            private readonly Control parent;
            private Control dropDownControl;
        }

        private readonly Control parent;
        private readonly Dictionary<string, UITypeEditor> uiTypeEditors;

        private WindowsFormsEditorService windowsFormsEditorService;
    }

Für TypeConverter:

   /// <summary>
    /// behandelt die TypeConverter der generierten Eigenschaften für das <see cref="PropertiesControl"/>
    /// </summary>
    internal class PropertiesControlTypeConverter : PropertiesControlTypeDescriptorContext
    {
        internal PropertiesControlTypeConverter(object instance)
            : base(instance)
        {
            this.typeConverters = new Dictionary<string, TypeConverter>();
        }

        /// <summary>
        /// liefert <see cref="TypeConverter"/> für akt. Eigenschaft (Eigenschaft wird gesetzt über <see cref="PropertiesControlTypeDescriptorContext.SetCurrentProperty"/>)
        /// </summary>
        private TypeConverter GetConverter()
        {
            TypeConverter tc;
            if (!typeConverters.TryGetValue(PropertyDescriptor.Name, out tc))
            {
                tc = GetConverter(Instance, PropertyDescriptor);
                typeConverters.Add(PropertyDescriptor.Name, tc);
            }
            return tc;
        }


        /// <summary>
        /// prüft ob akt. Eigenschaft (Eigenschaft wird gesetzt über <see cref="PropertiesControlTypeDescriptorContext.SetCurrentProperty"/>) <see cref="TypeConverter"/> gesetzt hat oder dessen Type
        /// </summary>
        /// <returns>true - <see cref="TypeConverter"/> ist gesetzt</returns>
        public bool HasConverter()
        {
            return (GetConverter() != null);
        }

        /// <summary>
        /// liefert Wert wie er angezeigt werden muss für akt. Eigenschaft (Eigenschaft wird gesetzt über <see cref="PropertiesControlTypeDescriptorContext.SetCurrentProperty"/>)
        /// </summary>
        /// <param name="value">akt. Wert aus Eigenschaft</param>
        /// <returns>Wert für Anzeige</returns>
        public virtual string GetPropertyTextValue(object value)
        {
            string str = null;
            try
            {
                str = GetConverter().ConvertToString(this, value);
            }
            catch (Exception)
            {
                //Exception durchfallen lassen kommt von Microsoft (aus: System.Windows.Forms.PropertyGridInternal.GridEntry.GetPropertyTextValue)
            }
            if (str == null)
            {
                str = string.Empty;
            }
            return str;
        }

        /// <summary>
        /// liefert Wert wie er in die Eigenschaft zurück geschrieben werden muss für akt. Eigenschaft (Eigenschaft wird gesetzt über <see cref="PropertiesControlTypeDescriptorContext.SetCurrentProperty"/>)
        /// </summary>
        /// <param name="str">akt. Wert laut Anzeige</param>
        /// <returns>Wert für Eigenschaft</returns>
        public virtual object SetPropertyTextValue(string str)
        {
            TypeConverter tc = GetConverter();
            if (tc.CanConvertFrom(this, typeof(string)))
            {
                return tc.ConvertFromString(this, str);
            }
            return str;
        }

        /// <summary>
        /// Returns whether this object supports a standard set of values that can be picked from a list, using the specified context.
        /// </summary>
        /// <returns>true if System.ComponentModel.TypeConverter.GetStandardValues() should be called to find a common set of values the object supports; otherwise, false.</returns>
        public bool GetStandardValuesSupported()
        {
            return GetConverter().GetStandardValuesSupported(this);
        }

        /// <summary>
        /// Returns a collection of standard values for the data type this type converter is designed for when provided with a format context.
        /// </summary>
        /// <returns>A ICollection that holds a standard set of valid values, or null if the data type does not support a standard set of values.</returns>
        public ICollection GetStandardValues()
        {
            return GetConverter().GetStandardValues(this);
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
                typeConverters.Clear();

            base.Dispose(disposing);
        }

        #region Statische Methoden

        /// <summary>
        /// liefert eine <see cref="TypeConverterAttribute"/> wenn gesetzt oder der Type der Eigenschaft dies gesetzt hat sonst null
        /// </summary>
        private static TypeConverter GetConverter(object instance, PropertyDescriptor propertyDescriptor)
        {
            //TypeConverterAttribute tca = null;
            //foreach (Attribute attr in propertyDescriptor.Attributes)
            //{
            //    if (attr is TypeConverterAttribute)
            //    {
            //        tca = (TypeConverterAttribute)attr;
            //        break;
            //    }
            //}

            //if (tca == null)
            //{
            //    object[] attrs = propertyDescriptor.PropertyType.GetCustomAttributes(typeof(TypeConverterAttribute), true);
            //    if (attrs.GetLength(0) > 0)
            //        tca = (TypeConverterAttribute)attrs[0];
            //}

            //if (tca != null)
            //{
            //    try
            //    {
            //        return (TypeConverter)Activator.CreateInstance(Type.GetType(tca.ConverterTypeName));
            //    }
            //    catch (MissingMethodException) //wenn kein Parameterloser Konstruktor (nur Parameter Type erlaubt)
            //    {
            //        return (TypeConverter)Activator.CreateInstance(Type.GetType(tca.ConverterTypeName), propertyDescriptor.PropertyType);
            //    }
            //}

            //return null;

            return propertyDescriptor.Converter;
        }

        /// <summary>
        /// prüft ob angegebene Eigenschaft <see cref="TypeConverterAttribute"/> gesetzt hat oder dessen Type
        /// </summary>
        /// <param name="instance">Instance aus der Eigenschaft stammt</param>
        /// <param name="propertyName">name der zu prüfenden Eigenschaft</param>
        /// <returns>true - <see cref="TypeConverterAttribute"/> ist gesetzt</returns>
        public static bool HasConverter(object instance, string propertyName)
        {
            return (GetConverter(instance, GetPropertyDescriptor(instance, propertyName)) != null);
        }

        #endregion

        private readonly Dictionary<string, TypeConverter> typeConverters;
    }

Im Prinzip dann nur SetCurrentProperty aufrufen mit HasEditor prüfen ob Editor angegeben wurde und mit EditValue kommt dann der Editor