SOLVED - EditorAttribute in PropertyGridItem aufnehmen



  • Hallo.

    Ich habe mir ein dynamisches Propertygrid erzeugt. Damit gelingt es mir, einfache Typen (Integer, String, etc.) dynamisch in eine Liste aufzunehmen und dann an ein Propertygrid zu übergeben.
    Jetzt würde ich gerne ein modales Dialogfeld, welches ich selbst erzeugt habe, als Editor verwenden.

    In Hardcode sieht das so aus:

    [EditorAttribute(typeof(MyEditorService), typeof(UITypeEditor))]
            [DisplayName("String by user editor")]
            [Description("Getting a string by a user defined editor")]
            [Category("General")]
            public string EditorStringAlias
            {
                get { return EditorString; }
                set
                {
                    EditorString= value;
                }
            }
    

    MyEditorService ist ein Erbe von UITypeEditor, wobei ich GetEditStyle und EditValue überschrieben habe. Funktioniert im Hardcode wunderbar. Nur weiß ich nicht, wie ich so ein Property dynamisch erzeugen kann.

    Mein PropertyGridItem anbei:

    public class MyPropertyGridItem
        {
            private bool _bFirstAssignment = true;
            private object _objValue;
            private object _objResetValue;
    
            public string DisplayName { get; set; }
    
            public string Name { get; internal set; }
    
            public string Category { get; set; }
    
            public string Description { get; set; }
    
            public string PropertyTypeName { get; set; }
    
            public object Value
            {
                get
                {
                    return _objValue;
                }
                set
                {
                    _objValue = value;
                    ResetValue = value;
                }
            }
    
            public object ResetValue
            {
                get
                {
                    return _objResetValue;
                }
                set
                {
                    if (_bFirstAssignment)
                    {
                        _bFirstAssignment = false;
                        _objResetValue = value;
                    }
                }
            }
    
            public object DefaultValue { get; set; }
    
            public bool ReadOnly { get; set; }
    
            public bool Browsable { get; set; }
    
            public string EditorTypeName { get; set; }
    
            public string ConverterTypeName { get; set; }
    
            public object Tag { get; set; }
        }
    

    Bis auf EditorAttribute ist alles aus dem HardCode enthalten. Aber ich bekomme die EditorAttribute nicht in mein PropertyGridItem.

    Kann mir jemand helfen?

    Ps.: Man kann z.B. für eine Schriftart ein Property dynamisch erzeugen, wobei ein vordefinierte Userdialog verwendet wird. Das würde so aussehen:

    DynamicData.Add("FontProperty", new MyPropertyGridItem
                {
                    DisplayName = "Font by Dialog",
                    PropertyTypeName = "System.Drawing.Font",
                    Description = "Definition eines Font.",
                    Category = "MyCategory",
                    Value = new Font("Arial", 8.25f),
                    ReadOnly = false,
                    DefaultValue = new Font("Arial", 8.25f),
                    ResetValue = new Font("Arial", 8.25f),
                    ConverterTypeName = "System.Drawing.FontConverter, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
                    EditorTypeName = "System.Drawing.Design.FontEditor, System.Drawing.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
                });
    

    Mehr zum dynamischen Erzeugen von Werten für ein Propertygrid findet ihr in meinem Post "Mehrere Dateninstanzen im Propertygrid anzeigen" in diesem Forum. Ich habe den dort verfolgten Weg, statische und dynamische Werte an ein PG zu übergeben, aufgegeben.



  • Versteh nicht ganz, was du mit dynamisch meinst. Es gibt irgendeine Schnittstelle, die man implementieren kann, um dynamische Properties im PropertyGrid bereitzustellen (könntest z.B. die Einträge von einem Dictionary auf die Weise anzeigen). ITypeInfoProvider oder irgendsowas. Lange her, wills jetzt nicht raussuchen. Findest du bestimmt, wenn du nach PropertyGrid und dynamic suchst.



  • Dynamisch bedeutet, dass ich eine statische Klasse mit einem Objekt-Array habe. Bevor ich die Klasse an das Propertygrid übergebe, lösche ich das Array und erzeuge es neu, wobei ich zur Laufzeit entscheiden kann, welche Elemente enthalten sein sollen. Das findet man unter PropertyGrid und dynamisch und das läuft schon.
    Jetzt geht es aber um den Spezialfall, dass ich einzelne Properties über eine selbst erzeugte UserForm ansprechen möchte, also ein modales Dialogfeld. Ich weiß, wie ich das Hardcoded (also statisch) bewerkstellige, nämlich in dem ich dem Property folgendes voranstelle:

    [EditorAttribute(typeof(MyEditorService), typeof(UITypeEditor))]
    

    Ich möchte jetzt diese Attribute in mein Array von PropertyGridItems aufnehmen - und das findest du nicht mal eben über PropertyGrid und dynamisch.

    Ich weiß, dass ich hier die letzten Tage recht oft aufschlage, aber ich habe schon sehr viel selbst gelöst - dynamisch funktioniert, eigener Editor funktioniert - nur die Kombination aus beidem nicht und da hänge wirklich schon seit drei Tagen dran.



  • Was ist DynamicData, was ist dein PropertyGridItem, der von nichts abgeleitet ist?

    Hab mal geschaut, die Schnittstelle, die ich meinte, heißt ICustomTypeDescriptor:

    http://www.codeproject.com/Articles/9280/Add-Remove-Items-to-from-PropertyGrid-at-Runtime



  • Hab es hin bekommen, auch wenn das wohl nicht der schönste Weg ist. Hier mal der komplette Code, sollte jemand das Problem auch mal haben:

    Code zum erstellen der dynamischen PropertyGridItemCollection:

    //Meine Werte
    private MyPropertyGridItemCollection DynamicData = new MyPropertyGridItemCollection();
    
    //Name des Editors bekommen
    EditorAttribute MyEditorAttributes = new EditorAttribute(typeof(MyEditorService), typeof(UITypeEditor));
    
    //Füge einen Wert für ein Integer hinzu, der über ein Userdialog eingegeben wird
                DynamicData.Add("UDInteger", new MyPropertyGridItem
                {
                    DisplayName = "Int with picker",
                    PropertyTypeName = "System.Int32",
                    Description = "Das ist ein System.Int32.",
                    Category = "Gruppe 2",
                    Value = 1,
                    DefaultValue = 0,
                    ReadOnly = false,
                    EditorTypeName = MyEditorAttributes.EditorTypeName
                });
    

    Dazu sind folgende Klassen nötig:

    MyPropertyGridItem

    public class MyPropertyGridItem
        {
            private bool _bFirstAssignment = true;
            private object _objValue;
            private object _objResetValue;
    
            public string DisplayName { get; set; }
    
            public string Name { get; internal set; }
    
            public string Category { get; set; }
    
            public string Description { get; set; }
    
            public string PropertyTypeName { get; set; }
    
            public object Value
            {
                get
                {
                    return _objValue;
                }
                set
                {
                    _objValue = value;
                    ResetValue = value;
                }
            }
    
            public object ResetValue
            {
                get
                {
                    return _objResetValue;
                }
                set
                {
                    if (_bFirstAssignment)
                    {
                        _bFirstAssignment = false;
                        _objResetValue = value;
                    }
                }
            }
    
            public object DefaultValue { get; set; }
    
            public bool ReadOnly { get; set; }
    
            public bool Browsable { get; set; }
    
            public string EditorTypeName { get; set; }
    
            public string ConverterTypeName { get; set; }
    
            public object Tag { get; set; }
        }
    

    MyPropertyGridItemDescriptor

    public class MyPropertyGridItemDescriptor : PropertyDescriptor
        {
            private MyPropertyGridItemCollection _objPropertyCollection = null;
    
            private string _strKey;
    
            private bool _bResetDefaultSwitch = true;
    
            public MyPropertyGridItemDescriptor(MyPropertyGridItemCollection objPropertyCollection, string strKey)
                : base(strKey, null)
            {
                this._objPropertyCollection = objPropertyCollection;
                this._strKey = strKey;
            }
    
            public override AttributeCollection Attributes
            {
                get
                {
                    return new AttributeCollection(null);
                }
            }
    
            public override bool CanResetValue(object component)
            {
                return true;
            }
    
            public override Type ComponentType
            {
                get
                {
                    return this._objPropertyCollection.GetType();
                }
            }
    
            public override string DisplayName
            {
                get
                {
                    return this._objPropertyCollection[_strKey].DisplayName;
                }
            }
    
            public override string Name
            {
                get
                {
                    return this._objPropertyCollection[_strKey].Name;
                }
            }
    
            public override string Category
            {
                get
                {
                    return this._objPropertyCollection[_strKey].Category;
                }
            }
    
            public override string Description
            {
                get
                {
                    return this._objPropertyCollection[_strKey].Description;
                }
            }
    
            public override bool IsReadOnly
            {
                get
                {
                    return this._objPropertyCollection[_strKey].ReadOnly;
                }
            }
    
            public override bool IsBrowsable
            {
                get
                {
                    return this._objPropertyCollection[_strKey].Browsable;
                }
            }
    
            public override object GetValue(object objComponent)
            {
                return this._objPropertyCollection[_strKey].Value;
            }
    
            public override void SetValue(object objComponent, object objValue)
            {
                this._objPropertyCollection[_strKey].Value = objValue;
            }
    
            public override Type PropertyType
            {
                get
                {
                    Type objType = Type.GetType(this._objPropertyCollection[_strKey].PropertyTypeName);
    
                    if (objType == null)
                    {
                        objType = typeof(System.String);
                    }
                    return objType;
                }
            }
    
            public override TypeConverter Converter
            {
                get
                {
                    if (this._objPropertyCollection[_strKey].ConverterTypeName == null)
                    {
                        return base.Converter;
                    }
                    else
                    {
                        Type objType = Type.GetType(this._objPropertyCollection[_strKey].ConverterTypeName);
                        return (TypeConverter)Activator.CreateInstance(objType);
                    }
                }
            }
    
            public override object GetEditor(Type editorBaseType)
            {
                if (this._objPropertyCollection[_strKey].EditorTypeName == null)
                {
                    return base.GetEditor(editorBaseType);
                }
                else
                {
                    Type objType = Type.GetType(this._objPropertyCollection[_strKey].EditorTypeName);
                    return Activator.CreateInstance(objType);
                }
            }
    
            public override void ResetValue(object objComponent)
            {
                if (_bResetDefaultSwitch)
                {
                    this._objPropertyCollection[_strKey].Value = this._objPropertyCollection[_strKey].ResetValue;
                    _bResetDefaultSwitch = false;
                }
                else
                {
                    this._objPropertyCollection[_strKey].Value = this._objPropertyCollection[_strKey].DefaultValue;
                    _bResetDefaultSwitch = true;
                }
            }
    
            public override bool ShouldSerializeValue(object objComponent)
            {
                if (this._objPropertyCollection[_strKey].Value == this._objPropertyCollection[_strKey].DefaultValue)
                {
                    return false;
                }
                else
                {
                    return true;
                }
            }
        }
    

    MyPropertyGridItemCollection

    public class MyPropertyGridItemCollection : IDictionary<string, MyPropertyGridItem>, ICustomTypeDescriptor
        {
            private Dictionary<string, MyPropertyGridItem> _cobData = new Dictionary<string, MyPropertyGridItem>();
    
            #region IDictionary<string,MyPropertyDataItem> Members
    
            public bool ContainsKey(string strKey)
            {
                return _cobData.ContainsKey(strKey);
            }
    
            public ICollection<string> Keys
            {
                get
                {
                    return _cobData.Keys;
                }
            }
    
            bool IDictionary<string, MyPropertyGridItem>.Remove(string strKey)
            {
                return _cobData.Remove(strKey);
            }
    
            public bool TryGetValue(string strKey, out MyPropertyGridItem objValue)
            {
                return _cobData.TryGetValue(strKey, out objValue);
            }
    
            public ICollection<MyPropertyGridItem> Values
            {
                get
                {
                    return _cobData.Values;
                }
            }
    
            public MyPropertyGridItem this[string strKey]
            {
                get
                {
                    return _cobData[strKey];
                }
                set
                {
                    _cobData[strKey] = value;
                }
            }
    
            public void Add(string strKey, MyPropertyGridItem objValue)
            {
                objValue.Name = strKey;
                _cobData.Add(strKey, objValue);
            }
            #endregion
    
            #region ICollection<KeyValuePair<string,MyPropertyDataItem>> Members
            public void Add(KeyValuePair<string, MyPropertyGridItem> objItem)
            {
                objItem.Value.Name = objItem.Key;
                _cobData.Add(objItem.Key, objItem.Value);
            }
    
            public void Clear()
            {
                _cobData.Clear();
            }
    
            public bool Contains(KeyValuePair<string, MyPropertyGridItem> objItem)
            {
                return _cobData.Contains(objItem);
            }
    
            public void CopyTo(KeyValuePair<string, MyPropertyGridItem>[] aobjData, int iArrayIndex)
            {
                throw new NotImplementedException();
            }
    
            public int Count
            {
                get
                {
                    return _cobData.Count;
                }
            }
    
            public bool IsReadOnly
            {
                get
                {
                    return false;
                }
            }
    
            public bool Remove(KeyValuePair<string, MyPropertyGridItem> objItem)
            {
                return _cobData.Remove(objItem.Key);
            }
    
            #endregion
    
            #region IEnumerable<KeyValuePair<string,MyPropertyDataItem>> Members
            public IEnumerator<KeyValuePair<string, MyPropertyGridItem>> GetEnumerator()
            {
                foreach (KeyValuePair<string, MyPropertyGridItem> objItem in _cobData)
                {
                    yield return objItem;
                }
            }
            #endregion
    
            #region IEnumerable Members
            IEnumerator IEnumerable.GetEnumerator()
            {
                return this.GetEnumerator();
            }
            #endregion
    
            #region ICustomTypeDescriptor Members
            public string GetClassName()
            {
                return TypeDescriptor.GetClassName(this, true);
            }
    
            public AttributeCollection GetAttributes()
            {
                return TypeDescriptor.GetAttributes(this, true);
            }
    
            public string GetComponentName()
            {
                return TypeDescriptor.GetComponentName(this, true);
            }
    
            public TypeConverter GetConverter()
            {
                return TypeDescriptor.GetConverter(this, true);
            }
    
            public EventDescriptor GetDefaultEvent()
            {
                return TypeDescriptor.GetDefaultEvent(this, true);
            }
    
            public PropertyDescriptor GetDefaultProperty()
            {
                return TypeDescriptor.GetDefaultProperty(this, true);
            }
    
            public object GetEditor(Type editorBaseType)
            {
                return TypeDescriptor.GetEditor(this, editorBaseType, true);
            }
    
            public EventDescriptorCollection GetEvents(Attribute[] aobjAttributes)
            {
                return TypeDescriptor.GetEvents(this, aobjAttributes, true);
            }
    
            public EventDescriptorCollection GetEvents()
            {
                return TypeDescriptor.GetEvents(this, true);
            }
    
            public object GetPropertyOwner(PropertyDescriptor objPropertyDescriptor)
            {
                return this;
            }
    
            public PropertyDescriptorCollection GetProperties(Attribute[] aobjAttributes)
            {
                return GetProperties();
            }
    
            public PropertyDescriptorCollection GetProperties()
            {
                MyPropertyGridItemDescriptor objDataPropertyDescriptor;
                PropertyDescriptorCollection cobjPropertyDescriptorCollection = new PropertyDescriptorCollection(null);
    
                foreach (KeyValuePair<string, MyPropertyGridItem> objItem in _cobData)
                {
                    objDataPropertyDescriptor = new MyPropertyGridItemDescriptor(this, objItem.Key);
                    cobjPropertyDescriptorCollection.Add(objDataPropertyDescriptor);
                }
                return cobjPropertyDescriptorCollection;
            }
            #endregion
        }
    

    Und dann noch die Vererbung des UITypeEditors

    class MyEditorService : UITypeEditor
        {
            public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
            {
                return UITypeEditorEditStyle.Modal;
            }
    
            public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
            {
                IWindowsFormsEditorService EditorService = provider.GetService(typeof(IWindowsFormsEditorService)) as IWindowsFormsEditorService;
    
                if (EditorService != null)
                {
                    DiagSelFam DSF = new DiagSelFam();
                    DSF.WindowsFormsEditorService = EditorService;
    
                    if (EditorService.ShowDialog(DSF) == DialogResult.OK)
                    {
                        System.Windows.Forms.ListBox.SelectedObjectCollection SelCol = new System.Windows.Forms.ListBox.SelectedObjectCollection(DSF.listBox1);
                        System.Text.StringBuilder ReturnString = new StringBuilder();
                        foreach (Object SOBJ in SelCol)
                        {
                            ReturnString.Append(SOBJ.ToString()).Append(";");
                        }
                        ReturnString.Remove(ReturnString.Length - 1, 1);
                        return ReturnString.ToString();
                    }
                }
    
                return null;
            }
        }
    


  • Und was ist die entscheidende Änderung?



  • Ich übergebe den Editor nicht über EditorAttribute, weil das kein Member von PropertyGridItem ist, sondern ich hole mir erstmal den Namen des Editors, in dem ich "extern" das EditorAttribute erstelle und mit der Methode EditorTypeName hole und übergebe diesen an EditorTypeName (das ist ein Member von PropertyGridItem).

    Dann klappt es. Der EditorTypeName ist etwas kryptisch und ich wusste auch nicht, wie ich diesen "erraten" soll. Der EditorTypeName für die Wahl von Farben, wie es von Windows zur Verfügung gestellt wird hat z.B. folgenden Namen:

    EditorTypeName = "System.Drawing.Design.ColorEditor, System.Drawing.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
    

    Das kann man sicher noch irgendwo nachlesen. Bei selbst erstellten Editoren... gibt es sicher auch eine Logik, die ich aber nicht durchschaue.


Log in to reply