Laden...

Geeignete Basisklasse für schliessbare Elemente in langen Listen

Erstellt von citizen.ron vor 16 Jahren Letzter Beitrag vor 16 Jahren 1.437 Views
citizen.ron Themenstarter:in
432 Beiträge seit 2005
vor 16 Jahren
Geeignete Basisklasse für schliessbare Elemente in langen Listen

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

49.485 Beiträge seit 2005
vor 16 Jahren

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

citizen.ron Themenstarter:in
432 Beiträge seit 2005
vor 16 Jahren

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