Laden...

PropertyGrid, Eigener TypeConverter, Componenten Properties anzeigen

Erstellt von thorstenst vor 11 Jahren Letzter Beitrag vor 11 Jahren 2.408 Views
T
thorstenst Themenstarter:in
18 Beiträge seit 2012
vor 11 Jahren
PropertyGrid, Eigener TypeConverter, Componenten Properties anzeigen

Hallo an alle, ich habe ein kleines Problem mit dem PropertyGrid und anzeigen eigener Werte die ich als Auswahl zur Verfügung stellen möchte.

In einer Klasse habe ich folgende ExtenderProviderProperty:


[ExtenderProvidedProperty]        
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]     
public List<TranslationInfo> GetTranslationSettings(IComponent component)
        {
            if (!_componentMapping.ContainsKey(component))
                _componentMapping.Add(component, new List<TranslationInfo>());

            return _componentMapping[component];            
        }

Die Klasse TranslationInfo sieht wie folgt aus:


  [Serializable]
    public sealed class TranslationInfo
    {
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public string TranslationKey { get; set; }

        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        [TypeConverter(typeof(TranslationPropertyConverter))]        
        public string TranslationProperty { get; set; }
    }

Wenn ich nun im PropertyGrid eines Controls die Eigenschaft TranslationSettings bearbeiten möchte bekomme ich auch wunderschön einen Standardeditor angezeigt in denen ich neue Instanzen von TranslationInfo erzeugen kann. (Siehe Anhang1)

Nun möchte ich aber an der Stelle wo die "1." im Screenshot steht, nur Properties anzeigen die vom Typ String sind.
Diese PropertyInfos möchte ich gerne aus der Componente auslesen, die ich in GetTranslationSettings() übergeben bekomme.

Wie das Auslesen funktioniert ist mir klar, nur wie komme ich an die Componente ran?
Ich hatte dies mit einem eigenem TypeConverter (TranslationPropertyConverter) vor (mit der GetStandardValues Methode), der für die TranslationProperty Property in der Klasse TranslationInfo zuständig ist. Nur wie komme ich von dort aus an die Componente?

Hat da jmd einen Rat? Weiß da grad nicht weiter.

Gruß
Thorsten

4.221 Beiträge seit 2005
vor 11 Jahren

Vermutlich suchst Du so was.... (... resp. daraus müsste sich was bauen lassen).

Im TypeConverter GetStandardValues...


public override System.ComponentModel.TypeConverter.StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
{

IDesignerHost iDesignerHost = context.Container as IDesignerHost;
Type type = Type.GetType(iDesignerHost.RootComponentClassName);

//oder

object o=iDesignerHost.RootComponent;



Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...

T
thorstenst Themenstarter:in
18 Beiträge seit 2012
vor 11 Jahren

Hmm leider nicht. contex.Container ist schon null somit der iDesignerHost auch.

Context gibt mir folgendes bei .ToString() raus:

System.Windows.Forms.PropertyGridInternal.PropertyDescriptorGridEntry TranslationProperty

Und context.Instance selbst ist auch vom Typ TranslationInfo, also die Klasse in der die Property ist die ich bearbeiten möchte. Aber die weiß ja nichts von nem Control/Componente 😦

T
thorstenst Themenstarter:in
18 Beiträge seit 2012
vor 11 Jahren

Hab noch folgendes versucht:
In GetStandardValues hole ich mir den IDesignerHost mittels


IDesignerHost o = context.GetService(typeof(IDesignerHost)) as IDesignerHost;

Jedoch ist die RootComponente die Componente (das UserControl) auf dem der TranslationProvider (IExtenderProvider) liegt und nicht die Componente von der ich die Properties bearbeite.

Nochmal vlt. im Bild zur Veranschaulichung.

Von dem Label (rot umrahmt) werden die Properties angezeigt. Der TranslationProvider fügt brav seine ExtendedProperty dem Control hinzu. Diese Liste kann ich auch bearbeiten. Aber ich möchte nun für die TranslationProperty-Property nur eine Liste von String-Properties aus dem LabelControl anzeigen. Aber an das Label komme ich nicht dran. Whaaaa....

4.221 Beiträge seit 2005
vor 11 Jahren

[ExtenderProvidedProperty]
 [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
 public List<TranslationInfo> GetTranslationSettings(IComponent component)
         {
             if (!_componentMapping.ContainsKey(component))
                 _componentMapping.Add(component, new List<TranslationInfo>());
 
            return _componentMapping[component];
         }

Wieso füllst Du nicht schon da die Liste ? component wäre doch Dein Label.

Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...

T
thorstenst Themenstarter:in
18 Beiträge seit 2012
vor 11 Jahren

hmm jaa das hatte ich mir auch gedacht. Nur wo speichere ich die Werte dann hin, damit ich auch im Type Converter dran komme. Möchte ungern in die TranslationInfo speichern, weil ich dann so gesehen ein Dummywert anlegen müsste.

T
thorstenst Themenstarter:in
18 Beiträge seit 2012
vor 11 Jahren

nochmal up. immer noch nicht gelöst 😦

49.485 Beiträge seit 2005
vor 11 Jahren

Hallo thorstenst,

ich habe mir jetzt nicht angeschaut, welche Möglichkeiten das PropertyGrid bietet und ob es da noch was besseres gibt. Aber mir scheint ist, als würde Programmierhans' Lösung grundsätzlich funktionieren. Nur dass eben die Frage offen ist, wo du die Information hinterlegen kann. Da sollte doch nun aber kein größeres Problem darstellen. Wenn alle Stricke reißen nimmst du ein Dictionary, dass zu jeder Komponente (oder jeder Property jeder Komponente) die gewünschte Information enthält.

herbivore

4.221 Beiträge seit 2005
vor 11 Jahren

Oder so:


public class TranslationInfoContainer : List<TranslationInfo>
{
private Component _Component=null;
public TranslationInfoContainer(Component pComponent)
{
   this._Component=pComponent;
}
}




So hast Du einerseits die Liste mit den TranslationInfos... kannst aber im Extender die Ref reinhauen...


[ExtenderProvidedProperty]
 [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public List<TranslationInfo> GetTranslationSettings(IComponent component)
          {
              if (!_componentMapping.ContainsKey(component))
                  _componentMapping.Add(component, new TranslationInfoContainer(component));
 
            return _componentMapping[component];
          }

So hättest Du die Component schon näher am Ziel (in der Klasse welche gleichzeitig die Liste ist).

Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...

T
thorstenst Themenstarter:in
18 Beiträge seit 2012
vor 11 Jahren

hallo Danke schonmal für Eure Antworten.

So wie Programmierhans das beschrieben hat, hatte ich das auch schon. Hab es nur Tag genannt 😉

Aber auch da komm ich nicht wirklich ran, da ich im Converter nur an das TranslationInfo object ran komme. Ich musste nen Weg finden um an die Dictionary ranzukommen in der die TranslationInfo steckt, dann könnte ich an das Tag/_Component ran kommen. Aber da habe ich noch keine Lösung für gefunden.

gruß thorsten

49.485 Beiträge seit 2005
vor 11 Jahren

Hallo thorstenst,

... da ich im Converter nur an das TranslationInfo object ran komme. Ich musste nen Weg finden um an die Dictionary ranzukommen in der die TranslationInfo steckt ...

da steht, du kommst an TranslationInfo ran und in der TranslationInfo steckt das Dictionary. Wo ist dann das Problem an das Dictionary ranzukommen?

herbivore

T
thorstenst Themenstarter:in
18 Beiträge seit 2012
vor 11 Jahren

Hallo herbivore,

ne leider nicht, es ist genau umgekehrt.

TranslationInfo ist nur nen object, was im Dictionary "drin steckt".
TranslationInfo hat als Property nur TranslationKey und TranslationInfo.

Deswegen heißt es ja auch

public class TranslationInfoContainer : List<TranslationInfo>

Die TranslationInfo "liegt" in einer List und die _List _Klasse kennt das Control (nach dem Beispiel von Programmierhans).

Aber sonst wäre es kein Problem gewesen 😄

Gruß
Thorsten

49.485 Beiträge seit 2005
vor 11 Jahren

Hallo thorstenst,

und was spricht gegen ein mehr oder weniger globales Dictionary?

herbivore

T
thorstenst Themenstarter:in
18 Beiträge seit 2012
vor 11 Jahren

Hi herbivore,

weil sogesehen jede TranslationProvider Klasse ihr eigenes

Dictionary<Componente, List<TranslationInfo>>

property besitzt und ich pro Formular einen TranslationProvider habe.
Und ich brauche die Information nur zur Design-Zeit.

Gruß
Thorsten

4.221 Beiträge seit 2005
vor 11 Jahren

Basierend auf meiner Idee könntest du ja das translationinfo um ein property vom type propertyinfo und component erweitern und so die translationinfo objekte schon aus dem extender erstellen. Da hast du ja Zugriff auf die component und somit auf dessen type. Per Reflection die Properties vom type string auslesen und pro property einen Eintrag im dict anlegen (mit ref auf component und propertyinfo).

Nicht was du haben wolltest... Dafür etwas was funktioniert.

Geschrieben auf dem Ipad auf dem Liegestuhl im Urlaub in Kroatien 😃

Sonnige Grüsse
Programmierhans

Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...

T
thorstenst Themenstarter:in
18 Beiträge seit 2012
vor 11 Jahren

Hallo Programmierhans,

vielen Dank für deine Antwort, ich werde es mir mal die Tage genauer anschauen.

Dann wünsch ich dir noch einen angenehmen Urlaub und genieße ihn (sprich: mach dein iPad aus ^^)

Gruß
Thorsten