Laden...

TabControl - Erstelltes Tab erscheint mittendrin und hat falschen Text

Erstellt von Tzigo vor 4 Jahren Letzter Beitrag vor 4 Jahren 1.404 Views
T
Tzigo Themenstarter:in
20 Beiträge seit 2019
vor 4 Jahren
TabControl - Erstelltes Tab erscheint mittendrin und hat falschen Text

Hallo erstmal in die Runde.

Wie im Titel schon angegeben habe ich ein paar Probleme mit einem TabControl in WinForms.

Wie herbivore schrieb, Code sagt mehr als tausend Worte, hier der grundlegende Code:


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            TabPage tab = new TabPage
            {
                Dock = DockStyle.Fill,
                Text = "new"
            };
            TabPage add = new TabPage
            {
                Dock = DockStyle.Fill,
                Text = "new " + (tabControl1.TabCount)
            };
            tabControl1.TabPages.Add(tab);
            tabControl1.TabPages.Add(add);
            RichTextBox rtb = new RichTextBox();
            rtb.Name = "rtb";
            rtb.Dock = DockStyle.Fill;
            rtb.AllowDrop = true;
            tab.Controls.Add(rtb);
        }


        private void tabControl_DrawItem(object sender, DrawItemEventArgs e)
        {
            try
            {
                var tabPage = this.tabControl1.TabPages[e.Index];
                var tabRect = this.tabControl1.GetTabRect(e.Index);
                tabRect.Inflate(-2, -2);
                if (e.Index == this.tabControl1.TabCount - 1)
                {
                    var addImage = Properties.Resources.add;
                    e.Graphics.DrawImage(addImage,
                        tabRect.Left + (tabRect.Width - addImage.Width) / 2,
                        tabRect.Top + (tabRect.Height - addImage.Height) / 2);
                }
                else
                {
                    var closeImage = Properties.Resources.close;
                    e.Graphics.DrawImage(closeImage,
                        (tabRect.Right - closeImage.Width),
                        tabRect.Top + (tabRect.Height - closeImage.Height) / 2);
                    TextRenderer.DrawText(e.Graphics, tabPage.Text, tabPage.Font,
                        tabRect, tabPage.ForeColor, TextFormatFlags.Left);
                }
            }
            catch (Exception ex) { throw new Exception(ex.Message); }
        }


        private void tabControl_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (tabControl1.SelectedIndex == tabControl1.TabPages.Count - 1)
                CreateTabPage();
        }

        private void CreateTabPage()
        {
            TabPage tab = new TabPage
            {
                Dock = DockStyle.Fill,
                Text = "new " + (tabControl1.TabCount)
            };
            tabControl1.TabPages.Add(tab);
            RichTextBox rtb = new RichTextBox();
            rtb.Name = "rtb";
            rtb.Dock = DockStyle.Fill;
            rtb.AllowDrop = true;
            tab.Controls.Add(rtb);
        }

        private void tabControl_MouseDown(object sender, MouseEventArgs e)
        {
            for (var i = 0; i < this.tabControl1.TabPages.Count - 1; i++)
            {
                var tabRect = this.tabControl1.GetTabRect(i);
                tabRect.Inflate(-2, -2);
                var closeImage = Properties.Resources.close;
                var imageRect = new Rectangle(
                    (tabRect.Right - closeImage.Width),
                    tabRect.Top + (tabRect.Height - closeImage.Height) / 2,
                    closeImage.Width,
                    closeImage.Height);
                if (imageRect.Contains(e.Location))
                {
                    this.tabControl1.TabPages.RemoveAt(i);
                    break;
                }
            }
        }

    }
}

Und noch das bisschen aus dem Designer:


namespace WindowsFormsApp1
{
    partial class Form1
    {
        /// <summary>
        /// Erforderliche Designervariable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// Verwendete Ressourcen bereinigen.
        /// </summary>
        /// <param name="disposing">True, wenn verwaltete Ressourcen gelöscht werden sollen; andernfalls False.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Vom Windows Form-Designer generierter Code

        /// <summary>
        /// Erforderliche Methode für die Designerunterstützung.
        /// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden.
        /// </summary>
        private void InitializeComponent()
        {
            this.tabControl1 = new System.Windows.Forms.TabControl();
            this.tabControl1.SuspendLayout();
            this.SuspendLayout();
            // 
            // tabControl1
            // 
            this.tabControl1.Dock = System.Windows.Forms.DockStyle.Fill;
            this.tabControl1.DrawMode = System.Windows.Forms.TabDrawMode.OwnerDrawFixed;
            this.tabControl1.Location = new System.Drawing.Point(0, 0);
            this.tabControl1.Name = "tabControl1";
            this.tabControl1.SelectedIndex = 0;
            this.tabControl1.Size = new System.Drawing.Size(800, 450);
            this.tabControl1.TabIndex = 0;
            this.tabControl1.Padding = new System.Drawing.Point(15, 4);
            this.tabControl1.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.tabControl_DrawItem);
            this.tabControl1.SelectedIndexChanged += new System.EventHandler(this.tabControl_SelectedIndexChanged);
            this.tabControl1.MouseDown += new System.Windows.Forms.MouseEventHandler(this.tabControl_MouseDown);
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(800, 450);
            this.Controls.Add(this.tabControl1);
            this.Name = "Form1";
            this.Text = "Form1";
            this.tabControl1.ResumeLayout(false);
            this.ResumeLayout(false);

        }

        #endregion

        private System.Windows.Forms.TabControl tabControl1;
    }
}

Das Problem welches ich habe ist dann folgendes:

Bei ersten drücken des AddTabs bekomme ich ein leeres Tab generiert (ohne die Richtextbox), manchmal auch zwischendrinn beim 4. oder 5. Tab zB. Außerdem bekomme ich immer wieder falschen TabText ausgegeben zB das ich 2x hintereinander new 1 oder auch haltmal 2x new 5.

Ich bin noch recht frisch in C# und stehe im Moment echt auf dem Schlauch und finde den Fehler nicht.

Ich freue mich auf Anregungen und Tips.

Grüße
Tzigo

B
357 Beiträge seit 2010
vor 4 Jahren

Was spricht zunächst mal dagegen, deine TabPages erst dann hinzuzufügen, wenn du sie fertig gebaut hast, also alle Controls platziert hast? Und sie vor allem dann auch gleich hinzufügst. Im Konstruktor erzeugst du zwei TabPages, wobei die zweite als Text gleich den Count der Collection mitbekommt, der zu dem Zeitpunkt aber immer 0 ist, weil du die erste Page noch gar nicht in die Collection gepackt hast.

Der Grund, warum dein RTC beim ersten Hinzufügen fehlt, ist der, dass zu diesem Zeitpunkt deine zweite Page, die du im Konstruktor erzeugt hast, ausgewählt wird. Diese hat aber, anders als Page 1, kein Rich Text Control. Daher ist das dann angezeigte TabControl leer. Ab dem dritten stimmt es wieder, weil du ja jedem neu hinzugefügten auch ein RTC mitgibst.

Wenn du den Text des Tabs immer vom TabCount abhängig machst, kann es natürlich vorkommen, dass Nummern doppelt vergeben werden. Ich erzeuge zu Beginn 4 Tabs:
new 1
new 2
new 3
new 4

So weit so gut. Jetzt lösche ich "new 3" raus und füge erneut eins an. Da ich jetzt aber wieder auf den Count gehe, hab ich jetzt halt folgendes dastehen:
new 1
new 2
new 4
new 4

Besser wäre es hier, du lässt einen eigenen Zähler mitlaufen, der die Zahl der bisher erzeugten Tabs beinhaltet und auch auf diese dann zugreifst.

T
Tzigo Themenstarter:in
20 Beiträge seit 2019
vor 4 Jahren

Hallo bredator,

danke für deine schnelle Antwort.
Du hast natürlich recht, manchmal sieht man wirklich den Wald vor lauter Bäumen nicht.

Danke dir!

Da kann ich vielleicht noch eine Anfängerfrage stellen:

ich würde gern alle RTBs durch eine Schleife jagen, um bei allen zB BackColor und ForeColor zu ändern.

Ich habs mit


            foreach (Control control in this.Controls)
            {
                if (control.GetType() == typeof(RichTextBox))
                {
                    control.BackColor = rtbBackColor;
                    control.ForeColor = rtbForeColor;
                }

            }

versucht, aber irgendendwie will es nicht.

B
357 Beiträge seit 2010
vor 4 Jahren

Wenn du this.Controls durchläufst, werden nur die Controls von Form1 iteriert. Du musst deine TabPage-Collection iterieren und dort dann die Richtextboxen suchen.

T
Tzigo Themenstarter:in
20 Beiträge seit 2019
vor 4 Jahren

Stimmt, ist ja recht simple... wieder was gelernt.

habs jetzt so gemacht:


            foreach (TabPage tb in tabControl1.TabPages)
            {

                foreach (RichTextBox rts in tb.Controls)
                {
                    rts.BackColor = rtbBackColor;
                    rts.ForeColor = rtbForeColor;
                }
            }

Danke nochmal und einen angenehmen Abend

Grüße
Tzigo