Laden...

eigenes Control, Properties Designer, Control Collection Problem

Erstellt von bhelbig vor 16 Jahren Letzter Beitrag vor 16 Jahren 1.480 Views
B
bhelbig Themenstarter:in
135 Beiträge seit 2006
vor 16 Jahren
eigenes Control, Properties Designer, Control Collection Problem

hi,

ich habe folgendes Problem. Ich habe ein eigenes Steuerelement (IBar) programmiert. Dies ist abgeleitet von UserControl und enthält eine Collection von QuickBarItems. Das funzt auch soweit. Ein QuickBarItem ist wiederum ein Steuerelement, welches abgeleitet ist von PictureBox. Mein Problem ist jetzt folgendes. Wenn ich in meinem Steuerelement IBar eine neues QuickBarItem Element meiner Collection hinzufügen will (geht ja über den Property Editor) tut er dies zwar, aber das hinzufügen des QuickBarItem Controls zur GUI haut nicht so ganz hin.

Meine Collection implementiert die IList. Beim hinzufügen über den Designer wird vom Property Editor folgende Methode aufgerufen:


            int IList.Add(object value)
            {
                if (!(value is QuickBarItem))
                {
                    throw new ArgumentException("value");
                }
                this.Add((QuickBarItem)value);
                return this.IndexOf((QuickBarItem)value);
            }

Diese Methode ruft dann wiederum die Add Methode in der IBar auf:


            public void Add(QuickBarItem value)
            {
                if (value == null)
                {
                    throw new ArgumentNullException("value");
                }
                this.owner.AddQuickBarItem(value);
                this.owner.Controls.Add(value);
                this.owner._pnlQuickBarContainer.Controls.Add(value);
                this.owner.intQuickBarItemCount++;
            }

Bei nur einem QuickBarItem funzt es. Sobald es mehr werden fügt er mir das QuickBarItem nicht mehr zum _pnlQuickBarContainer hinzu. Ich habe mittlerweile rausgefunden, dass es wohl am Name des QuickBarItems liegt. Wenn das Steuerelement kompiliert ist zeigt er mir zwar im Property Editor die automatisch erzeugten Namen "QuickBarItem1", "QuickBarItem2", usw. an, aber beim Debuggen, wenn ich folgende Zeile:


MessageBox.Show(value.Name.ToString());

nach der Zeile:


this.owner._pnlQuickBarContainer.Controls.Add(value);

einfüge zeigt er mir immer einen leeren String an. Ich kann das irgendwie nicht ganz nachvollziehen, vielleicht liege ich auch gänzlich falsch.
Ich hoffe ihr könnt mir weiterhelfen.

Grüße

Ben

B
bhelbig Themenstarter:in
135 Beiträge seit 2006
vor 16 Jahren

Hier mal ein Link wo mein Steuerelement liegt. Vielleicht kann sich das mal jemand anschauen. Es sollte einwandfrei kompilieren, beim Debuggen einfach ein QuickbarItem über den Eigenschafteditor im Designer hinzufügen und im ein Image zuweisen. Dann ein zweites QuickBarItem hinzufügen. Und ihr seht das Problem.

Danke schonmal für eure Hilfe.

http://nemo.provaris.net/downloads/itempWinCtrlLib.rar

O
778 Beiträge seit 2007
vor 16 Jahren

Ich vermute mal, das ganze Problem ist, dass du die Location der neu hinzugefügten QuickBarItems nicht einstellt. Sie kommen alle, aber sind dann alle uebereinander

B
bhelbig Themenstarter:in
135 Beiträge seit 2006
vor 16 Jahren

Hi Onlinegurke,

dass ist richtig ich setze die Location nicht, ich wollte das über Docks lösen. Hab ich anscheinend vergessen und ist mir garnicht aufgefallen.

Danke für den Hinweis.
Jetzt hab ich noch das Problem, dass die QuickBarItems zwar im Designer super dargestellt werden, aber wenn die Software kompiliert ist dann werden sie plötzlich nicht mehr angezeigt.
Ich hab gelesen, dass es etwas mit dem Attribut DesignerSerializationVisibility zu tun hat.
Ich war aber der Meinung, dass wenn ich


[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]

über die Property der QuickBarItems mache, dass die Items dann nach dem Compilieren noch vorhanden sind oder?

Grüße

Ben

O
778 Beiträge seit 2007
vor 16 Jahren

ja, das hat etwas damit zu tun. Deine Aufzaehlung gibts du aber wahrscheinlich nur als readonly property nach außen, da verursacht

[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]

natuerlich nur Fehler und wird nicht ausgefuehrt. Nimm stattdessen

[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]

Visible ist die Defaulteinstellungen. Das .NET-Framework ist aber scheinbar nicht intelligent genug, readonly propertys standardmaessig mit Content zu behandeln, deswegen muss das bei jedem einzelnen readonly property hin.

B
bhelbig Themenstarter:in
135 Beiträge seit 2006
vor 16 Jahren

Hey Onlinegurke, super, dass wars.

Einmal bräuchte ich deine Hilfe noch. Ich habe meiner Hauptkompnente IBar folgendes Attribut hinzugefügt:

[Designer("System.Windows.Forms.Design.ParentControlDesigner, System.Design", typeof(IDesigner))] 

Das sollte mir doch ermöglichen zur Designzeit andere Steuerelemente auf meinem zu platzieren. Allerdings werden, zumindest sieht es für mich so aus, die Steuerelemente die ich auf der IBar platziere im Hintergrund angezeigt. Da die IBar ja vom Typ UserControl ist kann das ja gut sein, dass .net da beim hinzufügen was in der Reihenfolge verwurschtelt.
Wenn ich damit richtig liege, weißt du vielleicht welche Methode ich überschreiben muss, damit beim Hinzufügen eines Steuerelements zu meiner IBar das neue Steuerelement in den Vordergrund gebracht wird?

Grüße

Ben

O
778 Beiträge seit 2007
vor 16 Jahren

IDesigner ist ein Irrweg. Ueberschreib die ControlCollection von QuickBar, und ueberschreibe da die Add-Methode.

//edit: Mittlerweile waere es glaub'ich sinnvoll den Namen des Threads mal zu aendern, weil es so ueberhaupt gar nicht um automatische Namensvergabe geht...

B
bhelbig Themenstarter:in
135 Beiträge seit 2006
vor 16 Jahren

Hi,

stimmt, das mit dem Themenname, allerdings sehe ich nicht wo ich den ändern kann. 🤔

Was ich nicht nachvollziehen kann ist, warum ich die ControlCollection von QuickBar überschreiben soll. Die QuickBar ist ja nur ein Teil des gesamten UserControls IBar und die IBar soll ja neue Controls aufnehmen können. Also müsste ich doch eigentlich die ControlCollection der IBar überschreiben. 🤔
Die IBar soll also sowas wie ein Panel sein. Das ist mein erstes eigenes Steuerelement und ich leider auch keine wirklich gute Literatur dazu gefunden.
Du hast mir da schon sehr viel weitergeholden.

Grüße

Ben

O
778 Beiträge seit 2007
vor 16 Jahren

sry ich meinte die ControlCollection der IBar, ja 🙂

Literatur gibts ganz wenig, stimmt 🙁 aber generell gibts dazu ein Beispiel von MS, TaskPane heissts glaub ich, hat mir seehr geholfen...

O
778 Beiträge seit 2007
vor 16 Jahren

ach ja, Namen des Threads aendern geht einfach, indem du den ersten Beitrag editierst...

B
bhelbig Themenstarter:in
135 Beiträge seit 2006
vor 16 Jahren

Sodale,

Titel geändert. Thx.

Also mit:


            iBar1.Controls.Add(button2);
            button2.BringToFront();

kann ich ein Control der IBar hinzufügen. Das Control wird dann auch im Vordergrund angezeigt, aber im Designer funzt es noch nicht. Ich weiß nicht ganz wie ich die Add Methode der controlCollection überschreiben soll.
Soll ich eine interne Klasse ControlCollection anlegen, die von ControlCollection erbt und darin dann die Add Methode überschreiben? In Add dann


base.Controls.Add(value)
value.BringToFront();

ausführen? Und wenn ich meine eigene ControlCollection habe, wie brinde ich den Designer dazu, diese zu verwenden und nicht die Standard ControlCollection?

Es ist wirklich schade, dass es keine richtige Literatur zur Control Entwicklung gibt. Das .net Framework ist so vielseitig, sich durch die Control Entwicklung zu kämpfen endet oftmals darin, dass man sich im Kreis dreht.

Grüße

Ben

B
bhelbig Themenstarter:in
135 Beiträge seit 2006
vor 16 Jahren

Also,

es ist zwar denke ich nicht gerade die eleganteste Lösung, aber sie funktioniert.
Ich habe einfach das bereits vorhandene Ereignis "OnControlAdded" genutzt. Dieses Ereignis habe ich in meinem UserControl verwendet und dort folgenden Code reingeschrieben:


e.Control.BringToFront();

natürlich muss dieses Ereignis auch bei allen SubControls die sich innerhalb des UserControls befinden eingebaut sein. Dort muss folgender Code rein:



            base.Controls.Add(e.Control);
            for (int intI = 0; intI < base.Controls.Count; intI++)
            {
                if (base.Controls[intI] == e.Control)
                {
                    base.Controls[intI].BringToFront();
                    break;
                }
            }

Das zweite Listing fügt also das vom Programmierer zur Designzeit hinzugefügte Control in die ControlCollection der Basisklasse also des Usercontrols hinzu und setzt es dann in der Z Reihenfolge nach vorne.
Das erste Listing greift natürlich nur, wenn der Programmierer zur Designzeit das neue Control direkt auf dem UserControl platziert.

Grüße

Ben