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...
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.
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.
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.
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:
wirft mir die IDE beim Versuch ein Control im RollupPanel zu plazieren die Fehlermeldung
Zitat
"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...
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.
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.
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!
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?
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.
Zitat
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.
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:
Zitat
...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?
^^. ich muss zugeben, da sich den designer auch nciht wirklich verwende. höchstens um schnell ein minitool zu bauen und dafür eine schnelle statische oberfläche zu bauen.