AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Programmieren allgemein Klassen dynamisch mit xsd verändern?
Thema durchsuchen
Ansicht
Themen-Optionen

Klassen dynamisch mit xsd verändern?

Ein Thema von jfheins · begonnen am 2. Dez 2009 · letzter Beitrag vom 15. Dez 2009
 
Benutzerbild von jfheins
jfheins

Registriert seit: 10. Jun 2004
Ort: Garching (TUM)
4.579 Beiträge
 
#10

Re: Klassen dynamisch mit xsd verändern?

  Alt 15. Dez 2009, 11:43
So, falls das nochmal wen interessiert, hier meine Lösung:

Der Graph (Containerklasse für Kanten und Knoten) implementiert das Interface ICustomTypeDescriptor - damit kann man dynamisch Zeilen im PropertyGrid hinzufügen.

Ein Feld in der Klasse dient als Sammelbecken für alle nicht-erkannten Attribute:
Code:
        private List<XAttribute> Attrib;
Dann muss man mindestens eine Methode wie folgt überschreiben:
Code:
        public PropertyDescriptorCollection GetProperties(Attribute[] attributes)
        {
            var normal = TypeDescriptor.GetProperties(this, attributes, true);

            var all = new List<PropertyDescriptor>(normal.Count + Attrib.Count);

            foreach (PropertyDescriptor item in normal)
            {
                all.Add(item);
            }

            foreach (var item in Attrib)
            {
                if (VariantDescriptor.Supports(item))
                {
                    all.Add(new VariantDescriptor(item));
                }
            }
           
            return new PropertyDescriptorCollection(all.ToArray());
        }
Den Rest kann man einfach weiterleiten:
Code:
        public string GetClassName()
        {
            return TypeDescriptor.GetClassName(this, true);
        }
        public string GetComponentName()
        {
            return TypeDescriptor.GetComponentName(this, true);
        }
        public TypeConverter GetConverter()
        {
            return TypeDescriptor.GetConverter(this, true);
        }
/// etc...
Und hier kommt der Interessante Teil: Der PropertyDescriptor der das typsichere Bearbeiten ermöglicht:
Code:
    /*  Diese Klasse leistet die Darstellung der verschidenen XAttribute
     *  im PropertyGrid. Es werden einfache Typen unterschieden, und zum
     *  Editieren in ihre C#-Equivalente überführt.
     *  Getestet mit int, float, double, decimal, string und DateTime, ggf. switches erweitern.
     *  Unbekannte Typen sollen nicht editierbar gemacht werden,
     *  wenn TypeCodeToType() den Wert null zurückgibt. (kann mit Supports() geprüft werden)
     * 
     *  Klasse benötigt Schema-Infos.
     * 
     */
    class VariantDescriptor : PropertyDescriptor
    {
        private XAttribute attr;
        private XmlTypeCode type;

        public VariantDescriptor(XAttribute attribute)
            : base(attribute.Name.ToString(), null)
        {
            attr = attribute;
            var info = attr.GetSchemaInfo();

            if (info == null)
                throw new ArgumentException("Schema-Info is required!\r\nUse XDocument.Validate(..., ..., true) or equivalent.");
           
            type = attr.GetSchemaInfo().SchemaType.TypeCode;
           
            if (TypeCodeToType(type) == null)
                throw new NotImplementedException(string.Format("This type (\"{0}\") is not supported.", type.ToString()));
        }

        public override bool CanResetValue(object component)
        {
            return false;
        }

        public override Type ComponentType
        {
            get { return typeof(Graph); }
        }

        public override object GetValue(object component)
        {
            switch (type)
            {
                case XmlTypeCode.Time:
                case XmlTypeCode.Date:
                case XmlTypeCode.DateTime:
                    return XmlConvert.ToDateTime(attr.Value, XmlDateTimeSerializationMode.RoundtripKind);

                // Konvertierung nötig, um das Dezimaltrennzeichen korrekt zu wandeln
                case XmlTypeCode.Decimal:
                    return XmlConvert.ToDecimal(attr.Value);
                case XmlTypeCode.Double:
                    return XmlConvert.ToDouble(attr.Value);
                case XmlTypeCode.Float:
                    return XmlConvert.ToSingle(attr.Value);

                default:
                    return attr.Value;
            }
        }

        public override bool IsReadOnly
        {
            get { return false; }
        }

        public override Type PropertyType
        {
            get
            {
                return TypeCodeToType(type);
            }
        }

        private static Type TypeCodeToType(XmlTypeCode TypeCode)
        {
            switch (TypeCode)
            {
                case XmlTypeCode.Boolean:
                    return typeof(Boolean);
                case XmlTypeCode.UnsignedByte:
                case XmlTypeCode.Byte:
                    return typeof(byte);
                case XmlTypeCode.Date:
                case XmlTypeCode.Time:
                case XmlTypeCode.DateTime:
                    return typeof(DateTime);
                case XmlTypeCode.Decimal:
                    return typeof(decimal);
                case XmlTypeCode.Double:
                    return typeof(double);
                case XmlTypeCode.Float:
                    return typeof(float);
                case XmlTypeCode.Int:
                    return typeof(int);
                case XmlTypeCode.NonPositiveInteger:
                case XmlTypeCode.NegativeInteger:
                case XmlTypeCode.Integer:
                case XmlTypeCode.Long:
                    return typeof(long);
                case XmlTypeCode.Short:
                    return typeof(short);
                case XmlTypeCode.Name:
                case XmlTypeCode.NCName:
                case XmlTypeCode.NmToken:
                case XmlTypeCode.Text:
                case XmlTypeCode.String:
                    return typeof(string);
                case XmlTypeCode.UnsignedInt:
                    return typeof(uint);
                case XmlTypeCode.NonNegativeInteger:
                case XmlTypeCode.PositiveInteger:
                case XmlTypeCode.UnsignedLong:
                    return typeof(ulong);
                case XmlTypeCode.UnsignedShort:
                    return typeof(ushort);
                default:
                    return null;
            }
        }

        public override void ResetValue(object component)
        {
        }

        public override void SetValue(object component, object value)
        {
            switch (type)
            {
                case XmlTypeCode.Time:
                case XmlTypeCode.Date:
                case XmlTypeCode.DateTime:
                    attr.Value = XmlConvert.ToString((DateTime)value, XmlDateTimeSerializationMode.RoundtripKind);
                    break;

                // Konvertierung nötig, um das Dezimaltrennzeichen korrekt zu wandeln
                case XmlTypeCode.Decimal:
                    attr.Value = XmlConvert.ToString((decimal)value);
                    break;
                case XmlTypeCode.Double:
                    attr.Value = XmlConvert.ToString((double)value);
                    break;
                case XmlTypeCode.Float:
                    attr.Value = XmlConvert.ToString((float)value);
                    break;

                default:
                    attr.Value = value.ToString();
                    break;
            }
        }

        public override bool ShouldSerializeValue(object component)
        {
            return false;
        }

        internal static bool Supports(XAttribute item)
        {
            return TypeCodeToType(item.GetSchemaInfo().SchemaType.TypeCode) != null;
        }
    }
Wenn jetzt ein objekt der Klasse graph einem properyGrid zugewiesen wird, erscheinen die zusätzlichen Attribute wie normale Eigenschaften und sind ebenso editierbar. Typsicherheit ist gegeben (z.B. "100000" ist kein gültiger wert für System.Short)
  Mit Zitat antworten Zitat
 


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:13 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz