none
CheckBox closen RRS feed

  • Frage

  • Hallo, 

    ich generiere dynamisch checkboxen auf einer Form. Diese möchte ich dann auch wieder schließen. 

    Momentan hab ich mir so geholfen: 

                                

    foreach (Control c in this.Controls) 
    {                        
          if (c is CheckBox)                        
             {                            
              c.Hide();                        
             }                    
    }

    so richtig schön, ist das allerdings nicht.(Oder?) Gibt es hier etwas sauberes?


    Danke!

    Mittwoch, 25. Dezember 2013 22:03

Antworten

  • Hi,
    hier mal eine Demo:

    using System;
    using System.Windows.Forms;
    
    namespace WindowsFormsApplication1
    {
      public partial class Form1 : Form
      {
        public Form1()
        {
          InitializeComponent();
        }
    
        private TextBox tb = new TextBox() { Top = 10, Left = 10 };
        private void Form1_Load(object sender, EventArgs e)
        {
          this.Controls.AddRange(new Control[] { tb });
          this.tb.KeyDown += tb_KeyDown;
        }
    
        void tb_KeyDown(object sender, KeyEventArgs e)
        {
          if (e.KeyCode == Keys.Enter) SetCBs();
        }
    
        private int dlz = 0;
    
        private void SetCBs()
        {
          // Löschen alter CheckBoxes
          for (int i = this.Controls.Count - 1; i >= 0; i--)
          {
            CheckBox cb = this.Controls[i] as CheckBox;
            if (cb != null)
            {
              ((CheckBox)this.Controls[i]).CheckedChanged -= cb_CheckedChanged;
              this.Controls.RemoveAt(i);
            }
          }
          // CheckBoxes neu anlegen
          dlz++;
          int n;
          if (int.TryParse(tb.Text, out n))
          {
            for (int i = 0; i < n; i++)
            {
              for (int k = 0; k < n; k++)
              {
                CheckBox cb = new CheckBox()
                {
                  Top = 50 + i * 30,
                  Left = 10 + k * 50,
                  Width = 45,
                  Tag = string.Format("Durchlauf {0}, Zeile {1}, Spalte {2}", dlz, i + 1, k + 1)
                };
                this.Controls.Add(cb);
                cb.CheckedChanged += cb_CheckedChanged;
              }
            }
          }
        }
    
        void cb_CheckedChanged(object sender, EventArgs e)
        {
          MessageBox.Show(((CheckBox)sender).Tag.ToString());
        }
    
      }
    }

    --
    Peter
    • Als Antwort markiert pmatula Donnerstag, 26. Dezember 2013 19:27
    Donnerstag, 26. Dezember 2013 18:42

Alle Antworten

  • Hi,
    wenn Du unter Schließen auch Entfernen verstehst, dann nimm die Remove-Methode, um die betreffende Checkbox aus der Controls-Auflistung zu entfernen. Wenn es danach auch keinen Verweis mehr auf die Checkbox gibt (Ereignis-Routine, Methodenvariablen, usw.), dann entsorgt der Garbage Collector die Checkbox ohne Rückstände.

    Mit der Hide-Methode bleibt die Checkbox als Objekt bestehen und belegt Speicherplatz, der bei dynamischer Erzeugung immer weiter anwächst.

    Zu beachten ist aber, dass Remove in einer foreach-Schleife zu Problemen führen kann, wenn wie in Deinem Codeausschnitt "c" mit Remove entfernt wird. Die von foreach am Anfang berechnete Menge für den ggf. intern genutzten Durchlaufzähler stimmt nach Remove nicht mehr und es kann zu einem Fehler kommen. Deshalb ist es besser, sich entweder die zu entfernenden Elemente zu merken und in einem zweiten Schritt zu entfernen oder die Auflistung rückwärts zu durchlaufen (for mit i--).

    --
    Peter

    Donnerstag, 26. Dezember 2013 05:35
  • Hi, danke für die Auskunft. Das mit remove funktioniert so und so bei mir nicht.

    Wenn ich diese Remove (ich bekomme keine Exception) entstehen aber komische "Konstrukte", er entfernt einige aber nicht alle CheckBoxen. 

    Das entsteht wenn ich mir vorher 5 2-dimensionale checkboxen erstelle lasse und dan nochmal draufklicke auf den generier-button und mit 2 2-dimensionale checkboen erstellen lasse. also die ersten 4 quadratisch angeordneten checkboxen sind intakt. aber warum er die anderen nicht löscht, ist mir ein rätsel? 

    Danke!

    PS: Ich muss mich korrigieren, die oberen 4 checkboxen arbeiten nicht ganz sauber. Ich habe ein changedChecked-Event hinterlegt, dass nicht korrekt abgearbeitet wird. (zumindestens optisch, im Hintergrund dürfts passen)


    • Bearbeitet pmatula Donnerstag, 26. Dezember 2013 09:10 Falschinformation
    Donnerstag, 26. Dezember 2013 09:09
  • Hallo pmatula,
    wie hast du denn versucht die CheckBoxen zu löschen?

    Angenommen, du willst alle Controls aus deinem 2 dimensionalem Array löschen, dann könnte das so gehen:

    for (int i = 0; i < checkBoxes.GetLength(0); ++i)//Spalte
    {
        for (int j = 0; j < checkBoxes.GetLength(1); ++j)//Zeile
        {
            this.Controls.Remove(checkBoxes[i, j]);
        }
    }

    Es werden wieder alle Elemente durch gegangen und dann aus der Auflistung gelöscht.

    Das andere wichtige hat Peter bereits geschrieben.


    Koopakiller [kuːpakɪllɐ] (Tom Lambert)
    Webseite | Code Beispiele | Facebook | Twitter | Snippets   C# ↔ VB.NET Konverter
    Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke.

    Donnerstag, 26. Dezember 2013 13:23
    Moderator
  • Hi,
    hier mal eine Demo:

    using System;
    using System.Windows.Forms;
    
    namespace WindowsFormsApplication1
    {
      public partial class Form1 : Form
      {
        public Form1()
        {
          InitializeComponent();
        }
    
        private TextBox tb = new TextBox() { Top = 10, Left = 10 };
        private void Form1_Load(object sender, EventArgs e)
        {
          this.Controls.AddRange(new Control[] { tb });
          this.tb.KeyDown += tb_KeyDown;
        }
    
        void tb_KeyDown(object sender, KeyEventArgs e)
        {
          if (e.KeyCode == Keys.Enter) SetCBs();
        }
    
        private int dlz = 0;
    
        private void SetCBs()
        {
          // Löschen alter CheckBoxes
          for (int i = this.Controls.Count - 1; i >= 0; i--)
          {
            CheckBox cb = this.Controls[i] as CheckBox;
            if (cb != null)
            {
              ((CheckBox)this.Controls[i]).CheckedChanged -= cb_CheckedChanged;
              this.Controls.RemoveAt(i);
            }
          }
          // CheckBoxes neu anlegen
          dlz++;
          int n;
          if (int.TryParse(tb.Text, out n))
          {
            for (int i = 0; i < n; i++)
            {
              for (int k = 0; k < n; k++)
              {
                CheckBox cb = new CheckBox()
                {
                  Top = 50 + i * 30,
                  Left = 10 + k * 50,
                  Width = 45,
                  Tag = string.Format("Durchlauf {0}, Zeile {1}, Spalte {2}", dlz, i + 1, k + 1)
                };
                this.Controls.Add(cb);
                cb.CheckedChanged += cb_CheckedChanged;
              }
            }
          }
        }
    
        void cb_CheckedChanged(object sender, EventArgs e)
        {
          MessageBox.Show(((CheckBox)sender).Tag.ToString());
        }
    
      }
    }

    --
    Peter
    • Als Antwort markiert pmatula Donnerstag, 26. Dezember 2013 19:27
    Donnerstag, 26. Dezember 2013 18:42
  • Hi, danke Peter. Hat gut funktioniert. 

    @Koopakiller - Aus einem komischen Grund, den ich nicht nachvollziehen kann, hat dein Codeschnippsel leider nicht funktioniert :(

    Donnerstag, 26. Dezember 2013 19:28