Posts Tagged ‘c# kontrolki’

Dynamiczne generowanie kontrolek

Author: Krzysztof Wawoczny (Krzysztof Wawoczny) | kwiecień 24th, 2010
avatar

W czasie pracy nad swoim małym projektem w C#, stanąłem przed problemem dynamicznego generowania kontrolek na formie. Nie chciałem, aby cały kod za to odpowiedzialny znajdował się w zdarzeniu kliknięcia w button, wiec stworzyłem przykładową klasę, którą nazwałem ControlGenerator.
klasa
Generalnie, trzeba by ją jakoś połączyć z główną formą aplikacji (w projekcie Form1 – standardowe nazewnictwo, gdyż więcej form nie przewiduję). W klasie ControlGenerator utworzyłem zmienną typu Form1 służącą za łącznik klasa – forma:

public class ControlGenerator
{
    /// Prywatna zmienna typu Form1
    private Form1 pf;
   //...
}

Następnie, konstruktor klasy musi posiadać takie przypisanie zmienej pf, aby wskazywała ona na referencję instancji mojej Form1 (trochę to może zamieszane, więc kawałek kodu wyjaśni, co miałem na myśli):

public ControlGenerator(Form1 f1)
{
  pf = f1;
}

Tak właśnie wygląda konstruktor, o którym była mowa, a jak to wygląda ‘na żywo’ jest ukazane poniżej.

W formie głównej aplikacji (Form1) po kliknięciu w jeden z przycisków powinny wygenerować się kontrolki, inicjuję więc obiekt klasy ControlGenerator w następujący sposób:

private void button1_Click(object sender, EventArgs e)
{
    ControlGenerator generate = new ControlGenerator(this);
   // właśnie tu do konstruktora przekazuje referencję do Form1 za pomocą this
}

Skoro moje połączenie klasa – forma jest już aktywne, to pora napisać metodę generującą kontrolki. Do owej metody powinna być przekazana informacja jak wiele kontrolek utworzyć. W poniższym przykładzie ograniczę się do wygenerowania TextBoxów z Labelkami zawartymi w GroupBoxie (które mogą być oczywiście dodatkowo osadzone na jakimś panelu, czy czymkolwiek się chce).
Gotowa funkcja prezentuje się następująco:

    public void GenerateRegisterControls(int number, string text)
    {
      int[] textboxes = new int[number];
      string[] labels = { "Imię", "Nazwisko", "PESEL", "Ulica", "Numer budynku",
                              "Miasto", "Kod pocztowy", "Województwo", "Telefon" };
      int i = 0, move = 0;

      //tworzę GroupBoxa, do którego wrzucę tworzone kontrolki (opis metody w następnym listingu)
      GroupBox box = GenerateGroupBoxControl(text); 

      foreach (int element in textboxes)
      {
        TextBox textbox = new TextBox(); //tworzę nowego TextBoxa
        Label label = new Label(); //tworzę nowy Label
        //lokalizacja TextBoxa
        textbox.Location = new System.Drawing.Point(200, 70 + move);
        textbox.Name = "textbox" + i.ToString();
        textbox.Size = new System.Drawing.Size(360, 20 + move); //wymiary TextBoxa
        //Rozmiar czcionki w TextBoxie - funkcja nie zostanie przedstawiona
        //w tym wpisie
        textbox.Font = SetFontForElement(40, textbox.Font);
        textbox.TabIndex = i;
        textbox.Visible = true;
        //automatyczna zmiana rozmiarów TextBoxa przy zmianie rozmiaru okna
        textbox.Anchor = AnchorStyles.Left | AnchorStyles.Top | AnchorStyles.Right;
        textbox.BorderStyle = BorderStyle.FixedSingle; //styl ramki
        //lokalizacja Labela
        label.Location = new System.Drawing.Point(20, 80 + move);
        label.Name = "label" + i.ToString();
        //nazwa Labela wzięta z wcześniej utworzonej tablicy stringów
        label.Text = labels[i];
        label.Font = SetFontForElement(28, label.Font);
        label.Size = new System.Drawing.Size(160, 28);
        label.Visible = true;

        box.Controls.Add(textbox); //dodaję do GroupBoxa utworzone TextBoxy
        box.Controls.Add(label); //dodaję do GroupBoxa utworzone Labele

        i++;
        move += 50;
      }
      //dodaję GroupBoxa z kontrolkami do panelu w kontenerze Form1
      pf.splitContainer1.Panel2.Controls.Add(box);
    }

Jak widać funkcja nie jest specjalnie skomplikowana, a tablicę z nazwami labelek można by przekazać jako parametr – jednak nie ma potrzeby w tym wpisie rozmieniać się na drobne. Tworzenie TextBoxów i Labelek można by dodatkowo zostawić osobnym funkcjom wywołanym w GenerateRegisterControls, jak np. GenerateGroupBoxControl, która wygląda następująco:

    private GroupBox GenerateGroupBoxControl(string text)
    {
      GroupBox box = new GroupBox();

      box.Name = "GroupBoxRegister";
      box.Text = text;
      box.Location = new System.Drawing.Point(1, 9);
      box.Size = new System.Drawing.Size(pf.splitContainer1.Panel2.Width - 20, pf.splitContainer1.Panel2.Height - 20);
      box.Anchor = AnchorStyles.Left | AnchorStyles.Top | AnchorStyles.Right | AnchorStyles.Bottom;

      return box;
    }

Samo wygenerowanie kontrolek po kliknięciu w jeden z przycisków wygląda następująco:

    private void button1_Click(object sender, EventArgs e)
    {
      ControlGenerator generate = new ControlGenerator(this);
      //9 TextBoxów i 9 Labelek, GroupBox będzie opatrzony tekstem Rejestracja
      generate.GenerateRegisterControls(9, "Rejestracja");
    }

Efekt:
efekt

Jeśli ktoś dopiero zaczyna swoją przygodę z C#, to informacje, które przedstawiłem z pewnością się przydadzą, albo przynajmniej wskażą drogę poszukiwań w google. AVE!