Laden...

Control aus XmlNode erzeugen

Erstellt von Momo592 vor 9 Jahren Letzter Beitrag vor 9 Jahren 4.063 Views
M
Momo592 Themenstarter:in
36 Beiträge seit 2014
vor 9 Jahren
Control aus XmlNode erzeugen

Hallo,

Ich würde gerne einige Controls (Panels, Buttons, etc.) anhand einer XML-Datei erzeugen. Jeder XmlNode soll dabei ein Objekt darstellen und die Eigenschaften des Objekts sollen aus den Attributen des XmlNode gelesen werden.

Leider habe ich keine Ahnung, wie ich aus einen XmlNode ein Object, bzw. ein Control erzeuge. Der Name des XmlNodes ist der Typ des zu erzeugenden Elements (z.B. Button). Ich müsste also ein Objekt vom Typ XmlNode.Name erzeugen können. Die zu verändernden Eigenschaften stehen halt in den Attributen des XmlNode. Das heißt ich stelle mir das in etwas in einer solchen Syntax vor:


TypVon(xnode.Name) neuesObjekt = new TypVon(xnode.Name);
foreach (XmlAttribute xatt in xnode.Attributes) 
{
  neuesObjekt.Eigenschaften["xatt.Name"] = xatt.Value;
}

Ich weiß ja, dass es genau so nicht funktioniert. Aber ich könnte mir vorstellen, das es so etwas in die Richtung gibt. Nur was? ?(

Ich bin sehr dankbar für jeden Lösungshinweis.

LG
Momo

T
314 Beiträge seit 2013
vor 9 Jahren

Nun, dann musst Du eben deine XML Typen auf die entsprechendn Controltypen mappen, diese mit den definierten Eigenschaften erzeugen und in gewünschten Container einfügen.

M
Momo592 Themenstarter:in
36 Beiträge seit 2014
vor 9 Jahren

So von der Logik kann ich der folgen. Zumindest klingt es relativ einfach. Kannst du mir ein Beispiel Codeschnipsel dazu geben? =)

771 Beiträge seit 2009
vor 9 Jahren

Entsprechen denn die Namen und Attribute genau den .NET-Controls?
Wenn ja, dann könntest du per Reflection die Typen erzeugen:


object neuesObjekt = Activator.CreateInstance(xnode.Name);

Und die einzelnen Eigenschaften dann per PropertyInfo.SetValue setzen.

Als Einstieg in das Thema kann ich dir Reflection in .NET empfehlen.
Oder hier aus dem Forum: [Artikel] Reflection und Metaprogrammierung

M
Momo592 Themenstarter:in
36 Beiträge seit 2014
vor 9 Jahren

Hallo Cat,

vielen Dank für deinen Beitrag. Werde mir die verlinkten Seiten mal genauer anschauen. 😃

M
Momo592 Themenstarter:in
36 Beiträge seit 2014
vor 9 Jahren

Also ich erkläre mein Problem wohl doch mal genauer, da ich irgendwie nicht so recht dahinter komme.

Die Kamera meines Chefs sendet bei Bewegungen vor Kamera Mails mit jeweils 5 Sekunden Video an ihn. Ich habe nun ein Programm geschrieben, das sein Outlook auf Mails von der Kamera durchsucht, die Videos abspeichert und diese im VLC-Player wiedergibt.
Nun werden seine Kameras aber immer mehr. Also will ich natürlich nicht jedes mal meinem Programm-Code an die Anzahl der Kameras anpassen. Ich habe mir also überlegt, dass ich über den Designer erstmal nur ein TabControl bereitstelle. Beim Programmstart will ich dann in der Settings-Datei nachschauen welche Kameras vorhanden sind. Dann für jede eine neue TabPage anlegen. Welche Controls dann die TabPages kommen, möchte aus einer XML-Datei auslesen, die dann etwa wie folgt aussieht:


<Panel>
   <Label>
   <Button>
   <Button>
<Panel>

In den Attributen der XML-Elemente wollte ich dann eben die Eigenschaften der Controls angeben. Die XML-Datei soll dann als Vorlage dienen, für jede neue TabPage die angelegt wird. Und dabei muss ich auch irgendwie den Namen des Objektes dynamisch generieren.

Weiß echt nicht, wie ich das machen soll. Und ich finde auch beim Suchen im Netz nichts, was in die Richtung geht. Das einzige könnte wohl sein, dass Serialisieren und Deserialisieren das ist, was ich suche. Aber bin mir da auch nicht so sicher.

T
314 Beiträge seit 2013
vor 9 Jahren

Was hat denn die Anzahl der Kameras damit zu tun?
Gefühlt hast Du eher ein Konzeptproblem.

M
Momo592 Themenstarter:in
36 Beiträge seit 2014
vor 9 Jahren

Also ich habe schon gemerkt, das nicht ganz klar wird, worauf ich hinaus will. Ist irgendwie auch schwer zu erklären. Daher habe ich mich jetzt erstmal an den Rat eines Kollegen gehalten und werde es "zu Fuß" versuchen. Da die Anzahl unterschiedlicher Controls und Eigenschaften die ich verwende sehr gering ist, kann ich das mit zwei Funktionen mit jeweils einer Switch-Verzweigung lösen. Das ist für den aktuell vorliegenden Fall auch ausreichend.

Nun tut sich mir aber ein neues Problem auf. Folgende Funktion erzeugt die benötigten Controls:


private void CreateControls(Control Parent, XmlNode XMLNode)
        {
            Control control;
            switch (XMLNode.Name)
            {
                case "Panel":
                    control = new Panel();
                    break;
                case "Label":
                    control = new Label();
                    break;
                case "Button":
                    control = new Button();
                    break;
                default:
                    control = new Control();
                    break;
            }
            Parent.Controls.Add(value: control);
            SetProperties(Control: control, XMLNodes: XMLNode.ChildNodes, Type: Type.GetType(XMLNode.Name));
        }

In der letzten Zeile seht ihr den Aufruf der Funktion SetProperties(...). Diese Funktion soll den gerade erzeugten Objekten dann die entsprechenden Eigenschaften zuweisen (welche in den ChildNodes des Nodes für das Control stehen). Jetzt stellen sich mir folgende Fragen:

  1. Muss ich das übergebene Control casten, damit ich die Eigenschaften komme?
  2. Die Namen der ChildNodes enthalten die Namen der Eigenschaften, sie liegen also als String vor. Wie komme ich nun über den String an die gleichnamige Eigenschaft? Geht das mit PropertyInfo? Und wenn ja, kann einer ein Beispiel liefern?

Vielen Dank für die bisherige und weitere Mühe, habe bei diesem Vorhaben mal wieder was gelernt. 😃

LG

709 Beiträge seit 2008
vor 9 Jahren

Die Namen der ChildNodes enthalten die Namen der Eigenschaften, sie liegen also als String vor. Wie komme ich nun über den String an die gleichnamige Eigenschaft? Geht das mit PropertyInfo? Und wenn ja, kann einer ein Beispiel liefern?


Control control = ...;

PropertyInfo propertyInfo = control.GetType().GetProperty("NameDerProperty");
propertyInfo.SetValue(control, "Wert");

Beachte aber, dass du den Wert als den Typen übergeben musst, der von der Eigenschaft verlangt wird.

M
Momo592 Themenstarter:in
36 Beiträge seit 2014
vor 9 Jahren

Vielen Dank!
Das ist ein großer Schritt nach vorne. Das mit dem dynamischen Casten kann ich wohl vergessen, dabei würde ja jegliche Typsicherheit verloren gehen.
Habe das mit dem Setzen der Eigenschaften erstmal so gelöst, dass ich den Wert auch mit dem richtigen Typen angebe. Hoffe das funktioniert bei allen Werten.


Control control = new Control();
PropertyInfo propInfo = control.GetType().GetProperty(XMLNode.Name);
propInfo.SetValue(control, Convert.ChangeType(XMLNode.InnerText, propInfo.PropertyType));

T
461 Beiträge seit 2013
vor 9 Jahren

Hallo,

also ich hab mal eine andere Frage:
.) Wieso ist das notwendig, die Controls definieren zu können? Sehen etwa die einzelnen Tabs jedesmal anders aus oder sind eh alle gleich?

Wenn es immer gleich ausschaut, könntest Dir das mit diesen Definitionen komplett sparen und die Sache anders angehen. Vorher müßte man wissen, ob das so ist wie ich schrieb?

Ich habe den Titel mal angepasst, so dass Suchende auch etwas damit anfangen können. EDIT: Ich sollte beim Wort "Shift" im Titel das "f" nicht vergessen... 😄

M
Momo592 Themenstarter:in
36 Beiträge seit 2014
vor 9 Jahren

Sie sehen jedes mal gleich aus. Die Funktionalität ist im Prinzip auch die gleiche. Wie wäre denn deine Idee? 😃

T
461 Beiträge seit 2013
vor 9 Jahren

Hier um es sich bildlich vorstellen zu können...

Die Daten können immer verschieden sein, jedoch immer mit der gleichen Datenklasse. Man setzt diese Datenklasse in die Modellklasse und diese kümmert sich fast alleine um das richtige Anzeigen in der Oberfläche..

Das einzige was sich da ändert, sind die Daten.

Ich habe den Titel mal angepasst, so dass Suchende auch etwas damit anfangen können. EDIT: Ich sollte beim Wort "Shift" im Titel das "f" nicht vergessen... 😄

M
Momo592 Themenstarter:in
36 Beiträge seit 2014
vor 9 Jahren

Verstehe noch nicht so ganz, was du mir damit sagen willst?

Also das Erzeugen der Controls aus einer XML-Datei funktioniert bereits. Ich kann auch meine Eigenschaften zu weisen. Bisher mache ich das aber alles zu Fuß (mit Switch-Verzweigungen). Folgender Code zum zuweisen der Eigenschaften funktionierte leider nicht:


PropertyInfo propInfo = Control.GetType().GetProperty(XMLNode.Name);
                propInfo.SetValue(Control, Convert.ChangeType(XMLNode.InnerText, propInfo.PropertyType));

Da eine Umwandlung von String in bestimmte Typen nicht möglich ist (z.B. bei Color oder Point).

Ist aber alles noch nicht so schlimm, da ich es bisher noch zu Fuß lösen kann. Aber nun würde ich gerne dynamisch meine Event-Handler zuweisen. In der Praxis ist es dann so, dass ich ein XML-Element habe, dessen Name der Name des Events ist (z.B. Click) und dessen InnerXML der Name der Funktion, die als Event-Handler verwendet werden soll (z.B. Button_Click).


<Events>
   <Click>Button_Click</Click>
   <MouseHover>Button_MouseHover</MouseHover>
   <MouseLeave>Button_MouseLeave</MouseLeave>
</Events>

Gibt es eine Funktion mit der ich nach Funktionsnamen suchen kann und die entsprechende Funktion als Delegaten zurück bekomme oder sowas?


control.Click = SucheFunktion(xnode.InnerXml);

LG

T
461 Beiträge seit 2013
vor 9 Jahren

Ähm, genau das war meine vorherige Frage, ob das UI immer gleich ausschaut oder der Aufbau dynamisch sein soll.

Wenn es immer gleich ausschaut, wozu benötigst du dann überhaupt diese komplexe Vorgehensweise um ein UI zusammen zu bauen?

Da könntest das alles komplett weg lassen, 1mal das UI im Editor erstellen und das eine UI immer wieder verwenden.

Ich habe den Titel mal angepasst, so dass Suchende auch etwas damit anfangen können. EDIT: Ich sollte beim Wort "Shift" im Titel das "f" nicht vergessen... 😄

M
Momo592 Themenstarter:in
36 Beiträge seit 2014
vor 9 Jahren

Ich verstehe was du meinst. Meine erste Idee war auch erst, dass ich das ein mal baue und dann einfach immer kopiere. Die zweite Idee war dann, das ganze in ein eigenes Steuerelement zu packen. Das wir mir aber etwas zu viel, da das eine Steuerelement ja viele Events für die einzelnen Button bereitstellen muss. Also habe ich gleich einen Schritt weiter gedacht und wollte es mit dynamischen Controls versuchen. Die Methode kann man dann in späteren Projekten wieder verwenden und man ist für die Zukunft vollkommen gerüstet. Aber wie so oft, scheint es gar nicht so schlau zu sein, es direkt auf die schönste Art zu versuchen. Also habe ich mit dem Auslesen der XML-Datei und dem Bearbeiten der Controls zu Fuß mehr oder weniger einen Kompromiss gemacht.

Ziel ist es aber nach wie vor, das ganze irgendwann völlig dynamisch zu machen. Weiß nur nicht, wo ich da einsteigen soll. Zwei Themen die ich dazu nun schon gehört/gelesen habe sind "Serialisieren/Deserialisieren" und "Reflection".

Und bei meiner letzten Frage (wie ich auf eine Methode, dessen Name in einem String steht, zugreife) habe ich die Befürchtung, dass es auch wieder auf Reflektion hinausläuft. Was aber ein sehr komplexes Thema zu sein scheint und ich es deshalb lieber auf später verschieben will. 👅

T
461 Beiträge seit 2013
vor 9 Jahren

Ok, verstehe, wohl genauso ein Perfektionist auf den Weg des besser werden wie ich! 😉

Dennoch sollte man mal einfach anfangen. Es kann später noch immer ausgebaut werden.

Aber eines habe ich nicht verstanden:

Das wir mir aber etwas zu viel, da das eine Steuerelement ja viele Events für die einzelnen Button bereitstellen muss.

Meinst du du erstellst ein UserControl oder ein benutzerdefiniertes Steuerelement?
Mit einem UseControl kann man das leicht umsetzen..

Ich habe den Titel mal angepasst, so dass Suchende auch etwas damit anfangen können. EDIT: Ich sollte beim Wort "Shift" im Titel das "f" nicht vergessen... 😄

M
Momo592 Themenstarter:in
36 Beiträge seit 2014
vor 9 Jahren

Ja es ist oft schwer, von der edelsten Lösung abzusehen und lieber die einfache zu nehmen. Meine einfachste war in diesem Fall der Weg zu Fuß. Und ich kann hinter nach und nach bestimmte Funktionen durch dynamische Funktionen ersetzen.

Aber mit Folgendem hast du mich nun etwas verwirrt:

Meinst du du erstellst ein UserControl oder ein benutzerdefiniertes Steuerelement?

Ich dachte bisher das wäre beides das gleiche. 8o

344 Beiträge seit 2006
vor 9 Jahren

Hallo,

ne ist nicht das gleiche.

Steuerelement ist ein Button. Jetzt kannst du von dem Standart Button ableiten und deine eigenen Funktionalitäten einbauen.

UserControl ist ein Contianer in dem du viele Steuerelemente hinzufügen kannst und dann in deine Tab als "Steuerelement" aufnehmen kannst. Ich glaube das ist das was du willst.

Gruss Lothi

M
Momo592 Themenstarter:in
36 Beiträge seit 2014
vor 9 Jahren

Aber ein UserControl erstelle ich doch auch in dem ich ein neues Projekt "Benutzerdefiniertes Steuerelement" anlege...

Also verstehe schon was du meinst. Und ich meinte wenn halt auch ein UserControl. Aber finde das mit dem UserControl zu unflexibel.

T
461 Beiträge seit 2013
vor 9 Jahren

Das mußt du genauer erklären, wo ist das bitte unflexibel?

Ich habe den Titel mal angepasst, so dass Suchende auch etwas damit anfangen können. EDIT: Ich sollte beim Wort "Shift" im Titel das "f" nicht vergessen... 😄

344 Beiträge seit 2006
vor 9 Jahren

Nun werden seine Kameras aber immer mehr. Also will ich natürlich nicht jedes mal meinem Programm-Code an die Anzahl der Kameras anpassen.

Du brauchst dann doch nur ein Button der dir eine neue Tab erstellt mit dem Usercontrol drin.
Das Usercontrol enthält ja dann auch alle Events.
Was da am Code anzupassen ist verstehe ich jetzt nicht. Machen doch alle das gleiche diese Dinger.

Gruss Lothi

M
Momo592 Themenstarter:in
36 Beiträge seit 2014
vor 9 Jahren

Scheinbar habe ich das mit den UserControls und Benutzerdefinierten Steuerelementen noch nicht ganz verstanden.

Also ein Benutzerdefiniertes Steuerelement ist einfach nur ein, das von einem bereits vorhandenen Steuerelement erbt, richtig?
Und ein UserControl ist ein Steuerelement, dass sich aus mehreren anderen zusammen setzt?

Letzteres hatte ich eigentlich getestet und konnte über das Steuerelement dann nicht ohne weiteres auf die Events der Buttons zu greifen.

Mit zu unflexibel meine ich, dass ich meine XML-Datei ja ändern kann, ohne das Programm neu compilieren zu müssen. Das Ziel ist ja, das irgendwann alles dynamisch läuft, sprich die Controls werden anhand der Elemente der XML erzeugt, die Eigenschaften dynamisch zugewiesen und letztendlich auch die Events. Dann kann ich über die XML-Datei z.B. einfach einen neuen Button mit entsprechenden Event hinzufügen. 😉

T
461 Beiträge seit 2013
vor 9 Jahren

Also ich persönlich hatte noch nie ein benutzerdefiniertes Steuerelement benötigt...

Wie nicht auf die Events im UserControl zugreifen?

Ich denke du vermischt die Funktionalitäten im MainWindow und in den UserControls miteinander..

Im UserControl müßte alles abgehandelt werden, was für deine Kameras notwenig ist. Das MainWindow sollte davon gar nix wissen müssen, sondern sich nur um das Handling der einzelenen Tabs kümmern. Das sollte man strikt trennen, Aufgabenteilung wenn du so willst..
Und das Benutzen von Events ist im Prinzip das Gleiche wie im MainWindow, nur halt dann im UserControl und sollte auch da drinnen bleiben.
(Wie auch immer deine Vorstellungen sind 🙂 )

Das alles irgendwann mehr konfigurieren zu können, hat eigentlich keinen größeren Umstand mit dieser vorgestellten Variante. Aber dazu kannst mal später fragen, wenn du mal die Basis geschaffen hast.. 😉

Ich habe den Titel mal angepasst, so dass Suchende auch etwas damit anfangen können. EDIT: Ich sollte beim Wort "Shift" im Titel das "f" nicht vergessen... 😄

M
Momo592 Themenstarter:in
36 Beiträge seit 2014
vor 9 Jahren

Ah jetzt habe ich dich verstanden. Ja ich wollte das UserControl wie ein normales Control in mein MainWindow mit aufnehmen und wie gewohnt damit arbeiten. Ehrlich gesagt bin ich auf die Idee, dass ich die Events direkt im UserControl zuweisen kann, noch nicht gekommen. 🤔

T
461 Beiträge seit 2013
vor 9 Jahren

Das sollte ca. so aussehen wie im Bild..

Ja, das UserControl kann ca. so behandelt werden wie ein Fenster, nur das es halt kein Fenster ist.

So ein UserControl kannst dann eigentlich egal wo oder egal wie oft verwenden.. je nach Abhängigkeiten..

Ich habe den Titel mal angepasst, so dass Suchende auch etwas damit anfangen können. EDIT: Ich sollte beim Wort "Shift" im Titel das "f" nicht vergessen... 😄

M
Momo592 Themenstarter:in
36 Beiträge seit 2014
vor 9 Jahren

Ich werde das mal ausprobieren. Ich danke dir! 👍

M
Momo592 Themenstarter:in
36 Beiträge seit 2014
vor 9 Jahren

Also ich sage nochmal vielen Dank! Soweit wie heute in nur wenigen Stunden, bin ich die ganze letzte Woche nicht gekommen. 👍 👍 👍