hi zusammen,
nachstehendes container user control habe ich zusammengebaut.
das problem ist, dass der container von sich aus per design einen header enthalten soll, der natürlich immer OBEN zu sehen sein soll -> DockStyle.Fill.
Sobald ich nun mein control benutze und ein control in ihm plaziere, wird es, wenn ich es nun ebenfalls mit DockStyle Fill anordne oberhalb des Headers angeordnet!!!
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
namespace Casa.CCL
{
[Designer("System.Windows.Forms.Design.ParentControlDesigner, System.Design", typeof(IDesigner))]
public partial class RollupPanel : Panel
{
private Panel _HeaderPanel;
public RollupPanel()
{
//SuspendLayout();
Dock = DockStyle.Top;
// Create a HeaderPanel
_HeaderPanel = new System.Windows.Forms.Panel();
_HeaderPanel.BackColor = System.Drawing.Color.DarkSeaGreen;
_HeaderPanel.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
_HeaderPanel.Dock = System.Windows.Forms.DockStyle.Top;
_HeaderPanel.Location = new System.Drawing.Point(0, 0);
_HeaderPanel.Name = "HeaderPanel";
_HeaderPanel.Size = new System.Drawing.Size(258, 23);
_HeaderPanel.TabIndex = 0;
Controls.Add(this._HeaderPanel);
InitializeComponent();
}
}
}
Nix kapisch, was musse nok makke?
bitte schnell mein leben retten, bin schon kurz vor dem sprung aus dem fenster...
thanx
ron
Hallo citizen.ron,
für den Fall, dass du noch nicht gesprungen bist, steht in vordrängelnde Controls (Control.Dock) eine Erklärung.
Für eine Lösung musst du wohl zwei interne Panels verwenden (also _headerPanel und z.B. _contentPanel) und es so managen, das this.Controls _contentPanel.Controls liefert, so dass von außen hinzugefügte Controls in dem Content-Panel landen.
herbivore
hi herbivore,
das mit dem ContentPanel war auch mein erster Gedanke.
da ich dann aber das ereignis ControlsAdded überwachen muss, sah mein code etwa so aus:
protected override void OnControlAdded(ControlEventArgs e)
{
this._ContentPanel.Controls.Add(e.Control);
this.Controls.Remove(e.Control); // wenn ich das nicht tue, bleibt das control zusätzlich im RollupPanel
}
ausserdem führt diese implementierung zu einer fehlermeldung sinngemäß:
_
"child" ist kein element des blabla-containers_
wenn ich zur entwurfszeit ein control in das RollupPanel plaziere.
???
tia
ron
Hallo citizen.ron,
erstens brauchst du den Event m.E. nicht, da du Panels.Controls problemlos überschreiben kannst:
public virtual ControlCollection Controls { get; }
Und zweitens wäre
this.Controls.Remove(e.Control);
schlicht überflüssig, da ein Control immer nur in einer ControlsCollection enthalten sein kann. Sprich das Add führt ein automatisches Remove in der alten Collection aus. Add reicht also.
herbivore
hi herbivore,
jetzt hast du mich komplett verloren.
wenn ich die controlcollection Controls überschreibe, was wäre dann dessen implementierung?
das hier❔
public virtual ControlCollection Controls
{
get { return _ContentPanel.Controls; }
}
wie würde ich denn dann dem RollupPanel selbst noch controls hinzufügen können, (z.b. _contentPanel und _headerPanel)?
also nochmal zurück zu der stelle wo es bei mir kracht:
die klasse hat im minimalmodus folgende implementierung:
{
[Designer("System.Windows.Forms.Design.ParentControlDesigner, System.Design", typeof(IDesigner))]
public partial class RollupPanel : Panel
{
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public Panel HeaderPanel;
private Panel _ContentPanel;
public RollupPanel()
{
Dock = DockStyle.Top;
// Create a HeaderPanel
HeaderPanel = new System.Windows.Forms.Panel();
HeaderPanel.BackColor = System.Drawing.Color.DarkSeaGreen;
HeaderPanel.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
HeaderPanel.Dock = System.Windows.Forms.DockStyle.Top;
HeaderPanel.Name = "_HeaderPanel";
HeaderPanel.Height = 23;
HeaderPanel.TabIndex = 0;
Controls.Add(this.HeaderPanel);
// Create a ContentPanel
_ContentPanel = new System.Windows.Forms.Panel();
_ContentPanel.BackColor = System.Drawing.Color.White;
_ContentPanel.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
_ContentPanel.Dock = System.Windows.Forms.DockStyle.Fill;
_ContentPanel.Name = "_ContentPanel";
_ContentPanel.TabIndex = 1;
Controls.Add(this._ContentPanel);
InitializeComponent();
}
}
Ohne das _contentPanel haben wir das Problem des Dockings, wie am Anfang des Threads beschrieben.
Mit _contentPanel ist das Problem, dass Elemente, die ich jetzt zur Entwurfszeit im RollupPanel plaziere, in den Hintergrund des _contentPanels treten! und nicht in ihm zu liegen kommen, also:
Fange ich, wie zuvor gezeigt, das Ereignis ControlAdded ab, mit nachstehender Implementierung:
protected override void OnControlAdded(ControlEventArgs e)
{
if ((e.Control.Name != this.Name) && (e.Control.Name != "_HeaderPanel") && (e.Control.Name != "_ContentPanel"))
{
_ContentPanel.Controls.Add(e.Control);
}
}
wirft mir die IDE beim Versuch ein Control im RollupPanel zu plazieren die Fehlermeldung
"child" ist kein untergeordnetes Steuerelement des übergeordneten Elements
aus.
und gleich noch ne frage:
wie kriege ich denn hin, dass zum beispiel zu entwurfszeit das headerpanel selektierbar ist (es zu veröffentlichen hat alleine nicht geholfen)?
bei einem splitterpanel bspw. sind doch zur entwurfszeit auch noch subelemente selektierbar.
und wie kann ich das ding eigentlich implementieren, ohne dass es überhaupt ein erbe von Panel ist? Die Schnittstelle IContainerControl scheint mir da nicht das richtige zu sein...
d.i.v.
ron
Hallo citizen.ron,
das hier?
im Prinzip ja, aber override statt virtual.
wie würde ich denn dann dem RollupPanel selbst noch controls hinzufügen können, (z.b. _contentPanel und _headerPanel)?
über base.Controls.Add
Ich denke die Folgefragen und auch das OnControlAdded erübrigt sich dann.
wie kriege ich denn hin, dass zum beispiel zu entwurfszeit das headerpanel selektierbar ist (es zu veröffentlichen hat alleine nicht geholfen)?
Sorry, mit Entwurfszeit kenne ich mich nicht aus. Ich benutze kein VS o.ä.
und wie kann ich das ding eigentlich implementieren, ohne dass es überhaupt ein erbe von Panel ist?
Warum soll es nicht von Panel erben? Ist doch gut.
herbivore
hey herbivore,
danke für deine hilfe, funzt jetzt.
nur für´s protokoll:
im Prinzip ja, aber override statt virtual.
liefert Fehlermeldung des Compilers:
RollupPanel.Controls.get": Der geerbte Member "System.Windows.Forms.Control.Controls.get" kann nicht überschrieben werden, weil er nicht als "virtual", "abstract" oder "override" markiert ist.
muss also virtual oder new bleiben.
thanx again
ron
Hallo citizen.ron,
dann hast du vermutlich noch 1.1. Unter 2.0 ist es virtual und deshalb wäre da override angezeigt.
herbivore
nope, ist 2.0,
hab aber rausgefunden, was uns auf den leim geschickt hat: in der online hilfe erscheint unter panel zunächst das panel aus dem namespace system.web.ui.webcontrols; dort ist das property tatsächlich als virtual deklariert.
der korrekte hilfetext ist bei mir unter
ms-help://MS.VSCC.v80/MS.MSDN.v80/MS.NETDEVFX.v20.de/CPref17/html/P_System_Windows_Forms_Control_Controls.htm
zu finden und nennt Controls tatsächlich nur als
public ControlCollection Controls { get; }
gruß
ron
Hallo!
Ich stehe gerade vor genau dem gleichen Problem. Gibt es dazu bereits eine Lösung?
Edit:
Hab mir gerade eine Lösung gebastelt, die einfach die Location der Childs korrigiert:
void GroupPanel_ControlAdded(object sender, ControlEventArgs e)
{
CorrectChildLocation(e.Control);
e.Control.LocationChanged += new EventHandler(Control_LocationChanged);
}
void Control_LocationChanged(object sender, EventArgs e)
{
CorrectChildLocation((Control)sender);
}
private void CorrectChildLocation(Control c)
{
if ((c.Location.Y <= header.Height)
c.Location = new Point(c.Location.X, header.Height + 1);
}
Wobei header das Control ist, das immer sichtbar ist und ich vor dem ControlAdded-Eventhandler eingefügt habe (mit Dock = DockStyle.Top).
Funkioniert einwandfrei!
mfg
Die oben genannte Lösung ist nicht ganz sauber, da trotzdem noch das Dock-Problem besteht, habe es jedoch gerade behoben. Falls Interesse besteht, werde ich den benötigten Code posten, sobald ich mit dem Testen fertig bin!
hi developerx,
hast du seinerzeit das docking-problem gelöst?
hi zusammen,
ich habe einen Panel-Erben, der in seinem Inneren eine GroupBox darstellt:
public class GroupPanel : Panel
{
#region Members
// Controls
private GroupBox groupBox;
#endregion
#region .ctor(s)
public GroupPanel() : base()
{
SetStyle( ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw | ControlStyles.SupportsTransparentBackColor, true );
Padding = new Padding(1);
// groupBox
groupBox = new GroupBox();
groupBox.Padding = new Padding(3, 3, 3, 3);
groupBox.Dock = DockStyle.Fill;
groupBox.Name = "groupBox";
groupBox.TabIndex = 0;
groupBox.BackColor = Color.Transparent;
base.Controls.Add(groupBox);
}
#endregion
}
Eingebettete Steuerelemente sollen jetzt in der GroupBox "landen", was zur Überschreibung von Controls führt:
#region Overrides
public virtual new ControlCollection Controls
{
get { return groupBox.Controls; }
}
protected override void OnControlAdded(ControlEventArgs e)
{
base.OnControlAdded(e);
e.Control.BringToFront();
}
#endregion
Mit der Padding-Eigenschaft des Panels wird nun logischerweise der Abstand der eingebetteten GroupBox vom Panel-Außenrand gesteuert.
Ich möchte aber den Abstand der nun in das Control platzierten Elemente zum GroupBox-Rand steuern können.
Hierfür habe ich eine Eigenschaft namens InnerPadding angelegt:
#region Properties
public virtual Padding InnerPadding
{
get { return groupBox.Padding; }
set { groupBox.Padding = value; }
}
#endregion
**Das Problem **:
Lege ich nun bspw. eine Textbox in das Control und docke es bspw. Bottom, wird es in die GroupBox gedockt, berücksichtigt aber das Padding der GroupBox nicht.
Ausserdem bin ich in der Lage, mit dem Designer das innere Steuerelemente aus den Grenzen der GroupBox herauszuziehen, also in den Bereich zwischen Panel-Außenrand und Groupbox - das darf ja eigentlich auch nicht sein.
Ich vermute man könnte das über die Eigenschaft ClientRectangle des Panels steuern, aber die ist ja schreibgeschützt.
Danke für Eure Hilfe
ron
Sieht jemand hier, was ich falsch mache oder nicht berücksichtige?
Hallo citizen.ron,
Lege ich nun bspw. eine Textbox in das Control und docke es bspw. Bottom, wird es in die GroupBox gedockt, berücksichtigt aber das Padding der GroupBox nicht.
also wenn das Control tatsächlich in der GroupBox landet, dann sollte auch deren Padding berücksichtigt werden.
Ausserdem bin ich in der Lage, mit dem Designer das innere Steuerelemente aus den Grenzen der GroupBox herauszuziehen, also in den Bereich zwischen Panel-Außenrand und Groupbox - das darf ja eigentlich auch nicht sein.
Also das der Designer durcheinander kommt, wenn du so "Schweinereien" machst, wie die Controls-Property zu überschreiben, finde ich mehr oder weniger unausweichlich.
herbivore
hi herbivore,
Also das der Designer durcheinander kommt, wenn du so "Schweinereien" machst, wie die Controls-Property zu überschreiben, finde ich mehr oder weniger unausweichlich.
Diese "Schweinerei" hat mir ein von mir hochgeachteter Experte dieses Forums im gleichen Thread vor zwei Jahren vorgeschlagen:
...da du Panels.Controls problemlos überschreiben kannst
Aber vielleicht hast Du deine Meinung ja inzwischen geändert 😉
Wie auch immer: m.E.n. ist es durchaus üblich, das Controls-Property auf ein ChildControl umzuleiten - das sieht man immer mal wieder auf einschlägigen C# Seiten.
Oder kennst Du einen anderen/besseren Weg, das Hinzufügen eines Steuerelements in einen untergeordneten Container des eigentlichen Controls umzuleiten?
Gruß
Ron
Hallo citizen.ron,
Aber vielleicht hast Du deine Meinung ja inzwischen geändert 😉
nö, ich benutze nur den Designer nicht. 🙂
Unabhängig vom Designer hat der Vorschlag leider nur den Makel, dass Controls nicht virtual ist. 🙂
herbivore
public class mycontrol : Control
{
protected override void OnControlAdded(ControlEventArgs e)
{
base.OnControlAdded(e);
otherControlCollection.Add(e.Control);
}
}
wenn man ein control einer anderen controlcolection zuweist, dann wird es vorher automatisch bei der alten collection ausgetragen.
nope,
das führt zu der Fehlermeldung
"child" ist kein untergeordnetes Steuerelement dieses übergeordneten Elements.
wenn man im designer ein steuerelement in das panel platziert.