Laden...

Auf sämtliche Komponenten der Form zugreifen

Erstellt von dennisspohr vor 15 Jahren Letzter Beitrag vor 15 Jahren 3.669 Views
dennisspohr Themenstarter:in
420 Beiträge seit 2007
vor 15 Jahren
Auf sämtliche Komponenten der Form zugreifen

Hallo,

wie kann ich auf sämtliche Komponenten der Form zugreifen? Zum Beispiel möchte ich die Texte aller Komponenten bearbeiten können.
Ist so etwas möglich?


Form.Container.Components

...ist bei mir immer null.

Danke für eure Hilfe!

Gruß Dennis

1.200 Beiträge seit 2007
vor 15 Jahren

Bist du dir sicher, dass du nicht Controls meinst?

Die ControlsCollection kannst du einfach über das Controls Property einer Control abgreifen.

Shift to the left, shift to the right!
Pop up, push down, byte, byte, byte!

YARRRRRR!

dennisspohr Themenstarter:in
420 Beiträge seit 2007
vor 15 Jahren

Hallo GMLOD,

ich bin auch zuallererst auf Controls gestoßen, allerdings ändert sich seltsamerweise immer nur ein einzige Button.

Gruß Dennis

1.200 Beiträge seit 2007
vor 15 Jahren

Du musst rekursiv da durchsteigen:

z.B.


private void SetTextForAllControls(String text, Control root)
{
    foreach(Control c in root.Controls)
    {
          SetTextForAllControls(text, c);
    }

    root.Text = text;
}

Shift to the left, shift to the right!
Pop up, push down, byte, byte, byte!

YARRRRRR!

dennisspohr Themenstarter:in
420 Beiträge seit 2007
vor 15 Jahren

Hallo GMLOD,

Du musst rekursiv da durchsteigen

Das habe ich gerade herausbekommen 🙂

Nun bekomme ich alle Buttons etc umbenannt.

Doch wie mache ich das z.B. mit dem HeaderText bei Columns?
Wenn ich ein Control erzeuge,

Control control = new Control();

enthält dieses Control das Propertie "Text", aber nicht "HeaderText". Wie könnte ich auf so etwas zugreifen?

Mal als Hintergrund: Ich möchte mir ein kleines Lokalisierungstool schreiben.

Gruß Dennis

1.200 Beiträge seit 2007
vor 15 Jahren

Mmmh, Du könntest ein switch Statement für den Typen (aControl.GetType()) einbauen und danach casten, bzw. spezielle Handler für bestimmte Controls einbauen.

Vielleicht kennt da jemand aber noch ne bessere Methoden.

Shift to the left, shift to the right!
Pop up, push down, byte, byte, byte!

YARRRRRR!

dennisspohr Themenstarter:in
420 Beiträge seit 2007
vor 15 Jahren

Hallo GMLOD,

ich denke ich werde es mit einem Switch machen, mir bleibt vorläufig wohl nicht viel mehr übrig.
Ich hoffe, dass ich alle Typen soweit abgedeckt bekomme und es nicht zu viele sind.


       if (root.GetType() == typeof(DataGridViewColumn))
       {
           DataGridViewColumn dataGridViewColumn = (DataGridViewColumn)root;
           dataGridViewColumn.HeaderText = "sdffg";
       }

root ist bei mir ein object. "In Wirklichkeit" natürlich ein Control. Allerdings lässt es sich nicht in ein DataGridViewColumn umwandeln.

Gruß Dennis

1.200 Beiträge seit 2007
vor 15 Jahren

An die Column wirst du auch nicht rankommen, nur an die DataGridView. Über die kannst du dann die Columns bekommen.

Shift to the left, shift to the right!
Pop up, push down, byte, byte, byte!

YARRRRRR!

dennisspohr Themenstarter:in
420 Beiträge seit 2007
vor 15 Jahren

Hallo GMLOD,

stimmt - klingt zumindestens um einiges logischer.

Allerdings funktioniert es nicht 🙁

 
        if (root.GetType() == typeof(DataGridView))
        {
            DataGridView dataGridView = (DataGridView)root;
            foreach (DataGridViewColumn column in dataGridView.Columns)
            {
                column.HeaderText = "sdffg";
            }
        }

Gruß Dennis

1.200 Beiträge seit 2007
vor 15 Jahren

Was funktioniert denn nicht? Was für eine Exception bekommst du?

Shift to the left, shift to the right!
Pop up, push down, byte, byte, byte!

YARRRRRR!

dennisspohr Themenstarter:in
420 Beiträge seit 2007
vor 15 Jahren

Hallo GMLOD,

(root.GetType() == typeof(DataGridView)

trifft niemals zu.


        private void SetTextForAllControls(object root)
        {
            Control root2 = (Control)root;

            foreach (object control in root2.Controls)
            {
                SetTextForAllControls(control);
            }

            if (root.GetType() == typeof(DataGridView))
            {
                DataGridView dataGridView = (DataGridView)root;

                foreach (DataGridViewColumn column in dataGridView.Columns)
                {
                    column.HeaderText = "sdffg";
                }
            }

            root2.Text = LG(root2.Text); // "sdffg";// LG(root2.Text);
        }

Gruß Dennis

1.200 Beiträge seit 2007
vor 15 Jahren

Das ist komisch. Ist deine DataGridView in einem UserControl untergebracht oder so?

Shift to the left, shift to the right!
Pop up, push down, byte, byte, byte!

YARRRRRR!

dennisspohr Themenstarter:in
420 Beiträge seit 2007
vor 15 Jahren

Hallo GMLOD,

sorry - mein Fehler.

Ich benutze ja das Krypton-ToolKit.. das heißt ich muss auf "KryptonDataGridView" abfragen. Nun funktionert es.

Gibt es eigentlich die Möglichekt, bei einem Object schon zu überprüfen, ob es ein Propertie namens "HeaderText" enthält? Oder geht das zu weit in den Code hinein?
Weil das wäre natürlich genial.. ich könnte alles viel automatisierter machen.

Gruß Dennis

1.200 Beiträge seit 2007
vor 15 Jahren

Mit Reflection könntest du das schon tun. Aber da müsste ich jetzt erst die MSDN wälzen um das genau zu sagen. Mach doch einfach nen neuen Thread dafür auf.

Shift to the left, shift to the right!
Pop up, push down, byte, byte, byte!

YARRRRRR!

dennisspohr Themenstarter:in
420 Beiträge seit 2007
vor 15 Jahren

Hallo GMLOD,

das werde ich tun.
Vielen Dank für deine Hilfe!

Gruß Dennis

dennisspohr Themenstarter:in
420 Beiträge seit 2007
vor 15 Jahren
Properties eines "object" herausfinden

Hallo,

abschweifend nochmal meine Frage:

Gibt es eigentlich die Möglichekt, bei einem Object schon zu überprüfen, ob es ein Propertie namens "HeaderText" enthält? Oder geht das zu weit in den Code hinein?
Weil das wäre natürlich genial.. ich könnte alles viel automatisierter machen.

Ich möchte mir ein kleines Lokalisierungs-Tool schreiben.
Am besten wäre es, wenn ich automatisiert überprüfen könnte, ob ein Object (was z.B. ein Button, DataGridViewColumn, etc) ein Propertie wie z.B. "Text", "HeaderText", Description" enthält.
Ist so etwas möglich? Vielleicht per Reflection?

Danke für eure Hilfe!

Gruß Dennis

S
902 Beiträge seit 2007
vor 15 Jahren

per reflection sicherlich, Eigesnchaften auslesen und schauen, ob eine entsprechend heisst!

mfg
serial

K
36 Beiträge seit 2008
vor 15 Jahren

class ReflectionHelper
{
    static bool DoesObjectHaveProperty(object objObject, string strPropertyName)
    {
        return (objObject.GetType().GetProperty(strPropertyName) != null);
    }
}

dennisspohr Themenstarter:in
420 Beiträge seit 2007
vor 15 Jahren

Hallo ihr beiden,

erstmal vielen Dank für eure Antworten!

Ich habe es folgendermaßen versucht:


            foreach (object control in (root as Control).Controls)
            {
                SetTextForAllControls(control);
            }

            PropertyInfo propertyInfo = root.GetType().GetProperty("Text");

            if (propertyInfo != null)
            {
                propertyInfo.SetValue(root, "fdsgufghufigh", null);
            }

Es funktioniert soweit 🙂

Ein kleine Frage noch:
Wenn ich nun den "HeaderText" eines DataGridViewColumns ändern möchte, wird es problematisch, da ich ja nur das DataGridView an sich erhalte. Dieses hat das Propertie "HeaderText" logischerweise nicht.
Gibt es eine Möglichkeit, an ALLE Properties des Controls zu kommen?

Gruß Dennis

K
36 Beiträge seit 2008
vor 15 Jahren
PropertyInfo[] objPropertyInfoArray = root.GetType().GetProperties();
dennisspohr Themenstarter:in
420 Beiträge seit 2007
vor 15 Jahren

Hallo,


PropertyInfo[] propertyInfos = root.GetType().GetProperties();

if (propertyInfos != null)
{
    foreach (PropertyInfo propertyInfo in propertyInfos)
    {
        if (propertyInfo.Name.ToLower() == "headertext")
        {
            propertyInfo.SetValue(root, "fdsgufghufigh", null);
        }
    }
}

mit "text" funktioniert es bei den Buttons, allerdings nicht mit "headertext" bei den Columns des DataGridViews...

Gruß Dennis

K
36 Beiträge seit 2008
vor 15 Jahren

Wenn ich dich richtig verstanden habe, dann ist root dein Form oder? Dann kommst du mit deinem jetzige Code doch gar nicht auf die DataGridViewColumn?

dennisspohr Themenstarter:in
420 Beiträge seit 2007
vor 15 Jahren

root ist ein Control. Und zwar alle Controls, die ich auf der Form finde, also z.B. auch ein DataGridView.

K
36 Beiträge seit 2008
vor 15 Jahren

Aber die DataGridViewColumn ist nicht direkt der Form, sonder dem DataGridView untergeordnet, richtig?

Also musst du darauf mit Hilfe von


foreach (DataGridViewColumn objColumn in root.dgvDataGridView.Columns)
{
    PropertyInfo objInfo = objColumn.GetType().GetProperty("HeaderText");
    //...
}

zugreiffen!

dennisspohr Themenstarter:in
420 Beiträge seit 2007
vor 15 Jahren

ja, aber ich möchte ja gerade umgehen, dass ich die Ccntrols kenne. Sagen wir mal, ich weiß gar nicht, das ein DataGridView existiert...
Weißt du, was ich meine?

K
36 Beiträge seit 2008
vor 15 Jahren

Ja, ich denke, ich hab dich verstanden.

Das wird aber wohl schwer werden. Du könntest sämtliche Controls überprüfen, ob diese wiederum eine Eigenschaft "Controls" oder eben "Columns" oä. enthalten und dann diese ebenfalls durchgehen. Und das gegebenenfalls rekursiv, bis keine Objekte mehr mit eben jenen Propertys vorhanden sind.

dennisspohr Themenstarter:in
420 Beiträge seit 2007
vor 15 Jahren

Aber mir bleibt wohl nichts anderes übrig, oder gibt es eine bessere Lösung?

Ich sehe gerade, dass auch simple, aber sehr wichtige Controls wie ein MenuStrips nicht funktionieren. Da die Texte der einzelnen Einträge ja im ToolStripMenuItem sind, nicht im MenuStrip selber.

F
10.010 Beiträge seit 2004
vor 15 Jahren

Nurmal so, du weisst, das Localization schon im FW eingebaut ist?

3.825 Beiträge seit 2006
vor 15 Jahren

Hallo Dennis,

statt


  if (root.GetType() == typeof(DataGridView))
        {
            DataGridView dataGridView = (DataGridView)root;
            foreach (DataGridViewColumn column in dataGridView.Columns)
            {
                column.HeaderText = "sdffg";
            }
        }

kannst Du


  if (root is DataGridView)
            foreach (DataGridViewColumn column in ((DataGridView)root).Columns)
                column.HeaderText = "sdffg";

schreiben. Ist kürzer und übersichtlicher.

Habs aber nicht getestet.

Grüße Bernd

Workshop : Datenbanken mit ADO.NET
Xamarin Mobile App : Finderwille Einsatz App
Unternehmenssoftware : Quasar-3

K
36 Beiträge seit 2008
vor 15 Jahren

Ich denke nicht, dass du eine andere Möglichkeit als das rekursive Durchlaufen der Controls hast.

Du musst eben immer darauf achten, dass Propertys wie "Controls", "Items", "Columns" etc. wiederum weitere Controls enthalten können.

X
1.177 Beiträge seit 2006
vor 15 Jahren

huhu,

zum Original-Problem:

ok, hatte es mir schon da gedacht: Lauf alle Controls durch und entscheide anhand vom Typen des Controls was du tun willst/musst.

z.B.

if (obj is DataGridViewColumn) {} else if (obj is MenuStrip) {}

Alternativ, da es ja "unendlich" viele Typen gibt: Chain of Responsibility ist vermutlich für den Fall dein Design Pattern. Der erste Handler versucht den Text zu setzen, da es kein Label ist darf es der nächste versuchen. Ok, keine Textbox, kein Panel, kein MenuStrip, aber ein Button.

Damit hältst du deinen Code "offener" aber die Laufzeit leidet bei deutlich mehr Typen die abgedeckt werden. Man könnte das noch auf Basisklassen erweitern, um die konkrete Klasse zu finden.

Eine allgemeingültige "Text-Implementation" gibt es nicht.

🙂

Xynratron

Herr, schmeiss Hirn vom Himmel - Autsch!

Die Erfahrung zeigt immer wieder, dass viele Probleme sich in Luft auslösen, wenn man sich den nötigen Abstand bzw. Schlaf gönnt.

49.485 Beiträge seit 2005
vor 15 Jahren

Hallo dennisspohr,

letztendlich geht es doch in beiden Threads um das gleiche Thema ==> zusammengefügt.

herbivore

dennisspohr Themenstarter:in
420 Beiträge seit 2007
vor 15 Jahren

Hallo,

nochmal vielen Dank für eure Hilfe.

Ich denke, alle Controls zu durchlaufen ist einfach zu langsam. Das schließe ich nun aus.

Nurmal so, du weisst, das Localization schon im FW eingebaut ist?

Ja ich weiß. Mal zu meiner Verständnis:
Ich doch bei der Localization des FW nur Controls übersetzen, keine Strings im "eigentlichen Quelltext" (z.B. MessageBoxes), oder?

Gruß Dennis

3.511 Beiträge seit 2005
vor 15 Jahren

Strings für MessageBoxen sollte man eh nie im Quelltext stehen haben. Diese gehören in Resourcedateien. Diese wiederum lassen sich mit den eingebauten .NET Mitteln auch lokalisierbar machen. Man erstellt dann für alle möglichen Sprachen die Ressourcendateien z.B. wie folgt


MeineStrings.resx
MeineStrings.de-DE.resx
MeineStrings.en-GB.resx

usw..., und greift dann nur auf die MeineStrings Ressource zu. .NET ermittelt dann die richtige ResX Datei. Findet er keine passende, nimmt der die Default (die ohne Kulturangabe).

"Jedes Ding hat drei Seiten, eine positive, eine negative und eine komische." (Karl Valentin)

dennisspohr Themenstarter:in
420 Beiträge seit 2007
vor 15 Jahren

Hallo Khalid,

vielen Dank für die Info.
Hört sich gut an, werde es wohl so machen.

Gruß Dennis

F
10.010 Beiträge seit 2004
vor 15 Jahren

Klar kannst du das, wenn du sie ( wie Khalid sagte ) in die Resource packst.

Hierzu ist das Kostenlose ResourceRefactoring Addin sehr nützlich ( wenn man nicht den Resharper hat ).
http://www.codeplex.com/ResourceRefactoring

dennisspohr Themenstarter:in
420 Beiträge seit 2007
vor 15 Jahren

Hallo FZelle,

vielen Dank für den Tipp. Ich werde das Tool mal ausprobieren 🙂

Gruß Dennis