Dynamisch Erzeugte Controls auf einem Panel zentrieren



  • Hallo Leute,

    ich erzeuge dynamisch Buttuns in einem Panel. Mal 7, mal 3, variabel halt. Im moment werden die linksbündig angeordnet( btn_x.Location(x,y)) und dann veränder ich halt nach jedem schleifendurchlauf die Position von x und y. jetzt möchte ich aber das die Controls zentriert angeordnet werden in dem Panel. Aber irgendwie stell ich mich grade total dämlich an das zu realisieren. Kann mir bitte jemand auf die Sprünge helfen? Vielen Dank



  • Welche Technologie?
    Was hast du bisher?



  • ich benutze Visiual Studio 2010 und programmiere mit c#

    bisher habe ich das

    private void button1_Click(object sender, EventArgs e)
            {
                Button[] btn = new Button[Convert.ToInt16(textBox1.Text)];
                int x = 10;
                int y = 20;
                for (int i=0; i <(Convert.ToInt16(textBox1.Text)); i++)
                {
                    btn[i] = new Button();
                    btn[i].Location = new Point(x, y);
                    btn[i].Size = new Size(50, 50);
                    this.panel1.Controls.Add(btn[i]);
                    x = x + 60;
                }
            }
    

    das panel geht über die ganze Form. Die Buttons werden jetzt halt links angeordnet sollen aber zentral werden...Für jede hilfe bin ich dankbar



  • Berechne die Position von Links. Ist ganz einfach.

    (Panelbreite - Controlbreite) / 2



  • Gibts in Forms keine Layout Container die das schon können?



  • inflames2k schrieb:

    Berechne die Position von Links. Ist ganz einfach.

    (Panelbreite - Controlbreite) / 2

    wenn ich das so mache ist der 1. Button in der Mitte. ich möchte aber zum beispiel wenn ich 3 buttons erzeuge das die miitte von dem zweiten button auch in der mitte von dem Panel ist. komisch komisch alle


  • Administrator

    David W schrieb:

    Gibts in Forms keine Layout Container die das schon können?

    Doch. Man könnte das TableLayoutPanel verwenden. 3 Kolonnen, linke Kolonne 50%, rechte Kolonne 50% und die in der Mitte auf AutoSize setzen.

    Grüssli



  • Klingt besser, dann kann er seine Buttons die Kürzer sind in der mittleren Spalte Links ausrichten ...

    //Edit:

    Les grad das er das gar nicht will ^^

    @tüfftüff
    du musst den Abstand natürlich für jedes Control separat berechnen, dann müssten alle Buttons in der Mitte sein.



  • gute ide emti dem tlp. hab ich nun so eingestellt( die Columms) aber wenn ich jetzt die buttons dadrin erstellen lasse dann packt er nur einen in die Mitte und danach kommt der nächste in die 3 kolonne. Mache ich zum beispiel einen 4 geht er in eine neue Reihe die ich gar nicht eingestellt habe. Aber hier mal mein code:

    private void button1_Click(object sender, EventArgs e)
            {
                Button[] btn = new Button[Convert.ToInt16(textBox1.Text)];
    
                for (int i=0; i <(Convert.ToInt16(textBox1.Text)); i++)
                {
                    btn[i] = new Button();
                    btn[i].Size = new Size(50, 50);
    
                    this.tableLayoutPanel1.Controls.Add(btn[i],1,0); 
    
                }
            }
    

  • Administrator

    Ehm, ja, du müsstest natürlich die Anzahl Kolonnen und Reihen nach deinen Bedürfnissen einstellen und deine Controls in die entsprechenden Zellen verteilen.

    Oder ich verstehe nicht so recht, was du eigentlich möchtest 😕

    Grüssli



  • na klar, du hast vollkommen recht! da hatte ich irgendwie ien brett vorm kopf. jetzt geht alles. Besten Dank



  • Eine Frage habe ich doch noch 🙂 und zwar erzeuge ich das TlP jetzt dynamisch, wi emache ich nun das ich ein bild was ich in einer zelle habe ändern kann? Er meckert die ganze zeit von:

    Fehler 1 "System.Windows.Forms.Control.ControlCollection" enthält keine Definition für "tlp", und es konnte keine Erweiterungsmethode "tlp" gefunden werden, die ein erstes Argument vom Typ "System.Windows.Forms.Control.ControlCollection" akzeptiert. (Fehlt eine Using-Direktive oder ein Assemblyverweis?)

    Das Tlp erzeuge ich so:

    //Panel erzeugen
    
                    TableLayoutPanel tlp = new TableLayoutPanel();
                    tlp.Location = new Point(21, 627);
                    tlp.Size = new Size(1551, 223);
                    tlp.Anchor = AnchorStyles.Top | AnchorStyles.Bottom |
                             AnchorStyles.Left | AnchorStyles.Right;
                   // tlp.CellBorderStyle = TableLayoutPanelCellBorderStyle.Single;
                    tlp.ColumnCount = contactListn.Count + 2;
                    tlp.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50));
                    for (int o = 1; o <= contactListn.Count; o++)
                    {
                        tlp.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize));
                    }
                    tlp.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50));
                    tlp.RowCount = 3;
                    tlp.RowStyles.Add(new RowStyle(SizeType.Percent, 10));
                    tlp.RowStyles.Add(new RowStyle(SizeType.Percent, 70));
                    tlp.RowStyles.Add(new RowStyle(SizeType.Percent, 20));
    
                    this.Controls.Add(tlp);
    

    Und versuche so auf das Tlp zuzugreifen. Hier kommt auch der Fehler

    foreach (System.Windows.Forms.PictureBox pbs in this.Controls.tlp)
                    {
                        if (pbs.Name == (sender.P_DISPLAYNAME + "s"))
                       .....
    

    Problem ist halt auf das Zugreifen auf die dynamisch erzeuge picturebox auf dem dynamisch erzeugen tablelayoutpanel.



  • Wenn deine beiden Code-Ausschnitte aus verschiedenen Methoden stammen, so mußt du halt die Variable 'tlp' als (privaten) Klassenmember deklarieren (und entsprechend initialisieren ;-).



  • this.Controls.tlp ist einfach Käse.
    Conrols ist eine ControlCollection http://msdn.microsoft.com/de-de/library/system.windows.forms.form.controlcollection(v=vs.80).aspx
    woher soll die dann plötzlich eine Collection "tpl" zur verfügung stellen.

    Du erwartest also das die Collection dir automatisch ein Property zur Verfügung stellt wo alle "TableLayoutPanel" Items enthalten sind ^^

    Da musst du dich schon selber drum kümmern, zb

    foreach (var control in this.Controls)
    {
        var tpl = control as TableLayoutPanel;
        if (tpl == null)
            continue;
    
        if (tpl.Name == (sender.P_DISPLAYNAME + "s"))
            .....
    

    Besser wäre es aber ohne Reflection aus zu kommen, vor allem wenn du die Controls vorher schon hast, da greift dann Th69s Kommentar.

    Bitte übernimm das nun nicht alles Pauschal, sondern versuche es genauer zu verstehen, das hilft dir mehr



  • Ja TH69 ist in 2 verschiedenen Methoden. Komme aber Grade nicht wirklich weiter mti deiner aussage. Ich mache eine klasse und dann initialisiere ich tlp als tablelayoutpanel oder wie?


  • Administrator

    tüfftüff schrieb:

    Ja TH69 ist in 2 verschiedenen Methoden. Komme aber Grade nicht wirklich weiter mti deiner aussage. Ich mache eine klasse und dann initialisiere ich tlp als tablelayoutpanel oder wie?

    Das sind Grundlagen der Sprache. Wieso beschäftigst du dich mit WinForms, wenn du nicht mal die Grundlagen der Sprache beherrschst? Lies dir nochmals die Grundlagen zu Variablen und Scopes durch und danach allenfalls auch noch zu Klassen.

    Grüssli



  • hallo mache es jetzt so:

    private TableLayoutPanel CreateLayoutpan()
            {
    
                pTablePanel = new TableLayoutPanel();
                pTablePanel.Location = new Point(21, 627);
                pTablePanel.Size = new Size(1551, 223);
                pTablePanel.Anchor = AnchorStyles.Top | AnchorStyles.Bottom |
                         AnchorStyles.Left | AnchorStyles.Right;
                pTablePanel.CellBorderStyle = TableLayoutPanelCellBorderStyle.Single;
                pTablePanel.ColumnCount = 7 + 2;
                pTablePanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50));
                for (int o = 1; o <= 7; o++)
                {
                    pTablePanel.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize));
                }
                pTablePanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50));
                pTablePanel.RowCount = 3;
                pTablePanel.RowStyles.Add(new RowStyle(SizeType.Percent, 10));
                pTablePanel.RowStyles.Add(new RowStyle(SizeType.Percent, 70));
                pTablePanel.RowStyles.Add(new RowStyle(SizeType.Percent, 20));
                return pTablePanel;
                }
    

    Soweit, so gut funktioniert auch wunderbar.
    Jetzt suche in das Tablelayoutpanel ab nach der Zelle wo eine bestimmte Picturebox ist. Auch das funktioniert. Möchte ich nun das bild der Picturebox ändern passiert einfach mal gar nichts. ich mache das im mOment so wie es vorher bei einem normalen panel auch schon geklappt hat und zwar so:

    foreach (System.Windows.Forms.PictureBox pbs in this.pTablePanel.Controls)
                    {
                        if (pbs.Name == (sender.P_DISPLAYNAME + "s"))
                        {
                            MessageBox.Show(Convert.ToString(pTablePanel.GetCellPosition(pbs)));
    
                            pbs.Image = neuesBild;
                            this.pTablePanel.Refresh();
    
                        }
                    }
    

    Die MessageBox zeigt auch die richtige Zellposition an. Nur das Bild ändert sich nicht. was mache ich falsch?
    Grüße


Anmelden zum Antworten