.
Anmeldung | Registrieren | Hilfe |
Suchen
Home Foren News Member Offers Termine Developer Blogs Knowledge Base

Navigation

Navigationslinks überspringen.
Knowledge Base reduzierenKnowledge Base
Tutorials reduzierenTutorials
Webentwicklung
Cliententwicklung
Datenbankentwicklung
IT Professional
Sharepoint
Sprachspezifisch reduzierenSprachspezifisch
C#
Visual Basic
C++
XAML
SQL
JavaScript
Erfahrungsberichte reduzierenErfahrungsberichte
Entwicklersoftware
Bücher
FAQ Grundlagen

Verknüpfungen

  • Knowledge Base durchsuchen
  • Hilfe zur Knowledge Base
  • RSS Feed
  • Twitter

Windows Forms Controls-Generierung zur Laufzeit

oder: Wie man sich Arbeit erspart, wenn man viele Buttons braucht.

Eines der Mitglieder des Forums fragte ob es möglich sei, viele Buttons automatisch erstellen zu lassen.
Der Trick dabei ist, dass man Controls (hier Buttons) erst zur Laufzeit erzeugt.

Eine weitere Anforderung war: Wenn man einen Rechtsklick auf einen der Buttons macht, soll dieser verschwinden.
Die Generierung von Controls ist schon die halbe Miete, aber natürlich muss man mit ihnen auch interagieren können. Dazu werden die Controls zentral registriert.
Wie das alles geht, zeigt dieser Artikel.

Alles was sie für das folgende Tutorial benötigen, ist ein TableLayoutPanel. Das ziehen sie in den Forms-Designer. Legen sie jetzt noch die Anzahl der Columns und Rows auf jeweils 3 fest. Dazu klicken sie auf das kleine schwarze Dreieck oben rechts am TableLayoutPanel.

ContextMenu

Klicken sie im Kontextmenü auf “Edit Rows and Columns”. Nun öffnet sich ein Fenster in dem sie die Verteilung der Spalten und Zeilen angeben können.

StylesEditor

Stellen sie die Breite jeder Column auf 33,33% ein. Das gleiche wiederholen sie mit den Rows.

Damit die Zellen auch noch sichtbar sind, wenn ein Button weggeklickt wurde, setzen sie “CellBorderStyle” im PropertyGrid auf “Outset”.

PropertyGrid

Zum Schluss wechseln sie im PropertyGrid auf die Eventliste und machen sie einen Doppelklick auf das MouseUp-Event.

Das war schon alles was sie zur Designzeit machen!

Das erste Listing zeigt den Form1 Code behind:

using System;
using System.Drawing;
using System.Windows.Forms;

namespace LaufzeitControlsRegistrierungUndHandling
{
   public partial class Form1 : Form
   {
      private readonly ControlsHandler controlHandler;

      public Form1()
      {
         InitializeComponent();
         FormBorderStyle = FormBorderStyle.Fixed3D;
         MaximizeBox = false;
         SizeGripStyle = SizeGripStyle.Hide;
         controlHandler = new ControlsHandler(this);
      }

      internal TableLayoutPanel @TableLayoutPanel
      {
         get { return this.buttonTableLayoutPanel; }
      }

      internal void OnButtonMouseUp(object sender, MouseEventArgs e)
      {
         var buttonReference = controlHandler.ButtonControlsRegistry[((Button)sender).Name];
         if(e.Button == MouseButtons.Right)
            buttonReference.Visible = !buttonReference.Visible;
      }

      internal void OnButtonTableLayoutPanelMouseUp(object sender, MouseEventArgs e)
      {
         var tableLayoutPanel = (TableLayoutPanel)sender;
         Control childAtPoint = tableLayoutPanel.GetChildAtPoint(new Point(e.X, e.Y));

         if(childAtPoint == null)
         {
            MessageBox.Show(String.Format("Control mit der ID {0}",
                                          e.X.ToString()
                                          + e.Y.ToString()
                                          + " konnte nicht gefunden werden."),
                            "Fehler!",
                            MessageBoxButtons.OK,
                            MessageBoxIcon.Warning);
            return;
         }
         if(e.Button == MouseButtons.Right)
            if(!controlHandler.ButtonControlsRegistry[childAtPoint.Name].Visible)
               controlHandler.ButtonControlsRegistry[childAtPoint.Name].Visible = true;
      }
   }
}

Richtig, alles was sie hier sehen, sind ein paar Grundeinstellungen für das Form, eine Referenz auf das TableLayoutPanel in Form eines Properties und EventHandler! Die Erzeugung der Controls und das Handling geschieht in einer anderen Klasse. Das nennt man Separation of Concerns und ist Bestandteil des Clean Code Developments (CCD).

Hier nun die ControlsHandler-Klasse:

using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;

namespace LaufzeitControlsRegistrierungUndHandling
{
   internal class ControlsHandler
   {
      private readonly Form1 formsReference;
      internal readonly Dictionary<string, Button> ButtonControlsRegistry;

      internal ControlsHandler(Form1 formsReference)
      {
         this.formsReference = formsReference;
         ButtonControlsRegistry = new Dictionary<string, Button>();
         PopulateTableLayoutPanel();
      }

      private void PopulateTableLayoutPanel()
      {
         formsReference.SuspendLayout();
         for(int column = 0; column < formsReference.TableLayoutPanel.ColumnCount; column++)
         {
            for(int row = 0; row < formsReference.TableLayoutPanel.RowCount; row++)
            {
               string id = column.ToString() + row.ToString();
               Button button = CreateButton(id);
               ButtonControlsRegistry.Add(id, button);
               formsReference.TableLayoutPanel.Controls.Add(button, column, row);
            }
         }
         formsReference.ResumeLayout(false);
      }

      private Button CreateButton(string id)
      {
         var button = new Button
         {
            Name = id,
            Size = new Size(50, 50),
            TabIndex = 0,
            Text = "X",
            UseVisualStyleBackColor = true,
            Visible = true
         };
         button.MouseUp += formsReference.OnButtonMouseUp;
         return button;
      }
   }
}

Die zentrale Registrierung der generierten Buttons übernimmt die ButtonControlsRegistry. Der key eines jeden Elements und gleichzeitig die ID für die jeweiligen Buttons wird aus einer Kombination der Spalten- und Zeilen-Nummer gebildet. Das MouseUp-Event jedes Buttons wird mit dem OnButtonMouseUp-EventHandler im Forms-Code verbunden.
Die fertigen Buttons werden über die PopulateTableLayoutPanel-Methode in die Tabelle eingefügt.

So sieht das Form zur Laufzeit aus:

FormAtRuntime

Wenn sie auf irgend einen der Buttons einen Rechtsklick machen, verschwindet dieser. Machen sie noch einen Rechtsklick in ein leeres Feld, erscheint der Button wieder.

von Rainer Hilmer, 28.07.2010 zugeordnet zu Cliententwicklung , Tutorials .

Kommentare

Es sind noch keine Kommentare vorhanden.

Eigener Kommentar

Sie müssen angemeldet sein, um ein Kommentar zu erstellen.
  • Schwierigkeit: Fortgeschrittene
  • Views: 1078
  • Zur Druckversion
  • Artikel von Rainer Hilmer

Kick it on dotnet-kicks.de

Artikel

Autor

Kick it!

Wenn ihnen dieser Artikel gefällt, bitte "kicken" sie ihn.

WPF Forum | ASP.NET Forum | ASP.NET MVC Forum | Silverlight Forum | Windows Phone 7 Forum | SharePoint Forum | Dotnet Jobs | Dotnet Termine | Developer Blogs | Dotnet News

Das Team | Regeln | Impressum