Hallo zusammen,
ich möchte in (scrollbaren) Listen von mehreren hundert Elementen ca. drei Texte, ein Image und eine Linie darstellen.
Mein aktueller Ansatz ist ein Control-Erbe, die alle mit DockStyle.Top in ein Panel eingefügt werden.
Die Elemente sollen die Zustände "Aufgeklappt" und "Geschlossen" kennen; im geschlossenen Zustand soll nur die Überschrift sichtbar sein (ähnlich Outlook MailItems, die ja im aufgeklappten Zustand z.B. eine Textvorschau enthalten).
Per Kontextmenü sollen natürlich alle Elemente der Liste ihren Zustand umschalten können und hier liegt der Flaschenhals.
Mein Ansatz ist ein UserPaint und nicht das tatsächliche Einbetten anderer Controls in das Topic (Label, PictureBox), aber ich weiß nicht, welche Methode von Control ich außer Paint überschreiben muss, um die Größe des Controls zu variieren, wenn es seinen Öffnungszustand ändert.
Ändere ich innerhalb der Methode OnPaint die Anweisung Size = new Size(...)
dann kann ich der Anwendung beim Malen zugucken...
Wann werden bspw. die Methoden "SetBoundsCore" bzw. "GetScaledBounds" vom Network aufgerufen? Offensichtlich nicht beim Neuzeichnen.
Nachstehender Code stellt die Klasse des Topic dar:
public class DBTopic : Control
{
#region Members
// lokal
private int index = 0;
// Property values
private int _ClosedSize = 16;
private int _OpenSize = 75;
private eTopicState _TopicState = eTopicState.Closed;
#endregion
#region Properties
public int ClosedSize
{
get { return _ClosedSize; }
set { _ClosedSize = value; }
}
public int OpenSize
{
get { return _OpenSize; }
set { _OpenSize = value; }
}
public eTopicState TopicState
{
get { return _TopicState; }
set
{
_TopicState = value;
Refresh();
}
}
#endregion
#region .ctor
public DBTopic(int i) : base()
{
index = i;
SetStyle(ControlStyles.UserPaint, true);
Dock = DockStyle.Top;
Size = new Size(Width, _ClosedSize);
}
#endregion
}
Nachstehender Code erzeugt die Elemente, ist sehr performant.
for (int i = 0; i < 200; i++)
{
DBTopic p = new DBTopic(i);
dict.Add(i, p);
}
DBTopic[] ar = new DBTopic[200];
dict.Values.CopyTo(ar, 0);
ControlPanel.Controls.AddRange(ar);
Nachstehender Code schaltet alle Elemente in den geöffneten Zustand um:
SuspendLayout();
foreach (DBTopic t in dict.Values)
{
t.TopicState = eTopicState.Open;
}
DBTopic[] ar = new DBTopic[200];
ResumeLayout();
ControlPanel.Refresh();
Nachstehender Code war mein Ansatz, die Größe des Elements von seinem Zustand abhängig zu machen, aber diese Methode wird nur beim Erzeugen des Elements aufgerufen, nicht beim Refresh():
protected override void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified)
{
if (TopicState == eTopicState.Open)
base.SetBoundsCore(x, y, width, _OpenSize, specified);
else
base.SetBoundsCore(x, y, width, _ClosedSize, specified);
}
Danke für Eure Tips
Gruß
Ron
Hallo citizen.ron,
du darfst das eben nicht als einzelne Controls machen, sondern musst in einem einzigen Control alles selber zeichnen. Siehe Optimierungsideen ?
Siehe auch:
[Tutorial] Zeichnen in Windows-Programmen (Paint/OnPaint, PictureBox)
[Tutorial] Gezeichnete Objekte mit der Maus verschieben
herbivore
danke herbivore,
diese beiträge klingen nach einem großartigen ansatz, auf den ich selbst wohl nicht gekommen wäre.
ich meld mich dann wieder, wenn beim ausprobieren die nächsten probleme auftauchen... 😉
gruß
cr