Zugriff aus CustomControl auf Parent-Attribut

mustang-1969

Grünschnabel
Hallo,

ich habe folgendes Problem und sitze wohl auf der Leitung:

In einem CustomControl 'mainControl' ist ein Panel und darin ein TabControl mit entsprechenden TabPages integriert.
In einem dieser TabPages ist ein weiteres CustomControl 'childControl' eingebettet.

Des weiteren existiert im 'mainControl' ein Attribut names 'm_temp'.

So - nun wollte ich aus dem 'childControl' auf das Attribut 'm_temp' zugreifen:
Code:
if (this.Parent.m_temp == irgendwas)
{ }
Dieser Versuch ist kläglich gescheitert, da das TabPage als Parent angesehen wird und nicht 'mainControl'!

Also greife ich nun mit
Code:
if ((mainControl)this.Parent.Parent.Parent.Parent).m_temp == irgendwas)
{ }
auf das benötigte Attribut zu.

Ich denke, da dies zu umständlich und zu fehlerträchtig ist, dass es bestimmt eine andere Lösung gibt, zumal bei mit noch weitere Controls in anderen TabPages darauf zugreifen müssen. Sollte während der Entwicklung eine weitere 'Ebene' (z.B. Panel, etc.) dazukommen/wegfallen, muss ich überall ein Parent wegnehmen oder dazustopseln.

Hat jemand einen sinnvolleren Lösungsvorschlag zum Zugriff auf das Attribut?

Grüsse Ralf
 
hmmmm......

ich glaube ich kann dir auch nicht weiterhelfen, wenn ich nicht weiss was irgendwas für ein Datentyp ist und du mir genau den Fehler nennst den der Compiler ausgibt
 
Hallo,

der Datentyp von 'irgendwas' ist Int32 - tut aber eigentlich nichts zur Sache. Der Compiler gibt mit dem Code
Code:
if ((mainControl)this.Parent.Parent.Parent.Parent).m_temp == irgendwas)
{ }
keinen Fehler aus, da dieser so funktioniert.

Mein Problem ist, dass ich nicht 4mal Parent angeben will, um auf das Attribut zugreifen zu können.
Ich denke, dass es doch viel einfacher zu lösen sein müsste!

Gruß Ralf
 
Definier dir doch einfach ein Makro:

Code:
#define PARENT ((mainControl)this.Parent.Parent.Parent.Parent)

wenn ich mich nicht irre.

Dann kannst du mit

Code:
PARENT.m_temp

darauf zugreifen.
 
Hallo Darkas,

hab's nachgeschlagen:
Code:
#define PARENT ....
geht nicht, da dies nur eine Präprozessordefinition ist um einen Bezeichner zu definieren, OHNE Wertezuweisung. (Für Debug-, Error- und Warningsbehandlung etc.)

Trotzdem danke für den Denkanstoß.

Gruß Ralf
 
Hallo,

ich denke ich habe jetzt selbst eine saubere Lösung gefunden.
Ich muss nämlich noch auf weitere Attribute zugreifen und auch mehrere andere ChildControls brauchen Zugriff darauf.

Also habe ich mich dazu entschlossen ala 'globale Variablen' eine Singleton-Klasse 'Schalter' zu erstellen, in der alle benötigten Attribute 'veröffentlicht' werden.
Unter http://www.yoda.arachsys.com/csharp/singleton.html ist übrigens meiner Meinung nach ein guter Beitrag zu Singletons.

Code:
using System;

namespace App
{
    public sealed class Schalter
    {
        static readonly Schalter instance = new Schalter();
        int _temp = 0;

        static Schalter()
        { }

        Schalter()
        { }

        public static Schalter Instance
        {
            get { return instance; }
        }

        public int Temp
        {
            get { return this._temp; }
            set { this._temp = value; }
        }
    }
}

So - nun kann von überall mit
Code:
if (Schalter.Instance.Temp == irgendwas)
{ ... }
auf die Attribute zugreifen, welche natürlich von 'mainControl' mit
Code:
Schalter.Instance.Temp = irgendwas;
gesetzt wurden. ;-)

Gruß Ralf
 
Ja, das ist natürlich auch einen Möglichkeit.

Ich hätte es zwar mit dem Makro gemacht, weil es ein bisschen Speicher spart aber die Lösung funktioniert ja auch.
 
Hallo darkas,

Ich hätte es zwar mit dem Makro gemacht, weil es ein bisschen Speicher spart aber die Lösung funktioniert ja auch.

OK - ich bin für alles offen. Wie soll das mit einem Makro funktionieren? Mit #define, wie Du es schon angedeutet hast geht es definitiv nicht und sonst finde ich im Netz zu C# und Makros nix Brauchbares!

Gruß Ralf
 
Also ich habe mal auf Wikipedia nachgeschlagen, und da steht auch dass es wo definiert wird.

Schreib halt einfach mal das Makro oben in deinen Quelltext und ersetze den anderen code, dann würde es sicher auch funktionieren
 
Hi Ralf!

Willkommen im Forum! :)

Der Artikel den Du da gefunden hast, ist wirklich sehr gut. :)
Der Singleton währe eine Möglichkeit. Du kannst diesen aber noch in anderer Form verwenden, sofern Du von einem Typ deiner Controls mehrere Instanzen hast und Du immer die Aktuelle ansprechen willst. Dafür definierst Dir ein Manager Objekt, welches Du auch in Form des Singelton Patterns bereit stellst. In dem Manager Objekt definierst dann Eigenschaften die das aktuelle Control repräsentieren sollen und speicherst sie darin sobald das entsprechende Control aktiviert wurde...

Aufrufe wie this.Parent.Parent.Parent.Parent sind völliger Schwachsinn. :) Erstens ist das Control.Parent Property dem Präsentationslayer vorbehalten und zweitens provozierst Du NullReferenceExceptions, bei deren Auslösung nicht mehr nachvollziehbar ist, welches Objekt null war, wenn versucht wurde trotzdem auf eine Eigenschaft zuzugreifen.
Es wird idR Regel verwendet um design-technische Dinge im Präsentations Layer durchzuführen (innerhalb des System.Windows.Forms Namespace und in den eigenen erweiterten Controls) und man darf es nicht für die Businesslogik missbrauchen.
Wenn man ein bestimmtes Parent im Präsentationslayer benötigt, muss man rekursiv durch dieses Property in der Control-Hierarchie nach oben "wandern", auf != null und bei Bedarf noch auf den Type prüfen und casten.
Rekursion
C#:
Control FindParent( Control parentControl, Type controlType )
{
	if ( parentControl != null && parentControl.GetType().Equals( controlType ) )
		return parentControl;
	else if( parentControl.Parent != null )
		// Rekursiver aufruf der Funktion
		return FindParent( parentControl.Parent, controlType );
	else return null;
}
Verwendung
C#:
MyControlType myControl = FindParent( this.Parent, typeof(MyControlType) ) as MyControlType;
if( myControl != null ) {
				
}
___________________________________________________________________________
hmmmm......

ich glaube ich kann dir auch nicht weiterhelfen, wenn ich nicht weiss was irgendwas für ein Datentyp ist und du mir genau den Fehler nennst den der Compiler ausgibt
Du hast Dir den ThreadStart nicht richtig durchgelesen, oder? Bitte Antworte nur, wenn Du präzise Angaben zu einem Problem machen kannst. Ich selber habe noch nie ein derartiges Makro gesehen.

Der #define Präprozessor gehört an den Anfang jeder *.cs Datei. Er definiert Konstanten, die zur Kompilierung/Ausführung von bestimmten Code-Abschnitten verwendet werden.
Daraus ergibt sich, dass an der Stelle weder mainControl noch this bekannt sein können. Möchte gerne mal wissen, was Du da auf Wikipedia gelesen hast. :confused:
 
Zurück