Wie kann ich einen Tab in einem TabControl deaktivieren?

81

Gibt es eine Möglichkeit, einen Tab in einem TabControl zu deaktivieren ?

Gold
quelle
1
Ich würde entweder die Registerkarte entfernen oder ihren Inhalt durch eine Erklärung ersetzen ...
Phil1970

Antworten:

71

Die TabPage- Klasse verbirgt die Enabled-Eigenschaft. Das war beabsichtigt, da es ein unangenehmes UI-Designproblem gibt. Das grundlegende Problem ist, dass durch Deaktivieren der Seite nicht auch die Registerkarte deaktiviert wird. Wenn Sie versuchen, dies zu umgehen, indem Sie die Registerkarte mit dem Auswahlereignis deaktivieren, funktioniert dies nicht, wenn das TabControl nur eine Seite enthält.

Wenn Sie diese Usability-Probleme nicht betreffen, denken Sie daran, dass die Eigenschaft weiterhin funktioniert. Sie ist lediglich vor IntelliSense verborgen. Wenn die FUD unangenehm ist, können Sie dies einfach tun:

public static void EnableTab(TabPage page, bool enable) {
    foreach (Control ctl in page.Controls) ctl.Enabled = enable;
}
Hans Passant
quelle
3
Ich frage mich, was ist die Hintergrundgeschichte dafür, dass das Umschalten der Tab-Sichtbarkeit nicht erlaubt ist
Shekhar,
91

Verwandeln Sie Ihre TabPage in ein Steuerelement und setzen Sie die Enabled-Eigenschaft auf false.

((Control)this.tabPage).Enabled = false;

Daher ist der Header der Registerkarte weiterhin aktiviert, der Inhalt jedoch deaktiviert.

Cédric Guillemette
quelle
3
Ich denke, dies verfehlt den Punkt, die Registerkarte selbst zu deaktivieren. Der Benutzer soll es nicht auswählen und den Inhalt sehen können.
ThunderGr
3
Das mag Ihr Anwendungsfall sein, aber ich denke, es ist nützlich, wenn die Registerkarte aufgrund einiger Rechte schreibgeschützt sein muss.
Cédric Guillemette
8
Warum muss TabPage zur Steuerung heruntergestuft werden? Aufgrund des Polymorphismus können wir die Enabled-Eigenschaft von TabPage aus aufrufen.
Eldar Agalarov
1
Ich bin mir nicht sicher, ob es jemals anders war, aber heute ist es völliger Unsinn. 69 Aufsteiger im Unrecht. Autsch ..
TaW
1
@TaW Diese Frage beantwortet die Frage spezifisch und präzise. "Gibt es eine Möglichkeit, einen Tab in einer Tabcontrol zu deaktivieren?" Sie fragen nicht, wie man einen Tab versteckt. 69 Upvoter rechts ... 1 Kommentator, der die Frage nicht falsch gelesen hat. Autsch ...
DDuffy
69

Sie können einfach verwenden:

tabPage.Enabled = false;

Diese Eigenschaft wird nicht angezeigt, funktioniert jedoch problemlos.

Sie können das Auswahlereignis so programmieren TabControler, dass kein Wechsel zu einer nicht bearbeitbaren Registerkarte möglich ist:

private void tabControler_Selecting(object sender, TabControlCancelEventArgs e)
{
    if (e.TabPageIndex < 0) return;
    e.Cancel = !e.TabPage.Enabled;
}
Lecsox
quelle
3
Wie bizarr ... das scheint auch für die VisibleEigenschaft zu gelten, obwohl es beim Testen keinen visuellen Effekt zu haben schien.
Alfie
@Alfie Das liegt daran, dass TabPage von der folgenden Hierarchie erbt: Control> ScrollableControl> Panel> TabPage, das Verhalten Enable, Visible usw. ist polymorph.
Meister Yoda
49

Sie können das Ereignis "Auswählen" registrieren und die Navigation zur Registerkarte abbrechen:

private void tabControl1_Selecting(object sender, TabControlCancelEventArgs e)
{
    if (e.TabPage == tabPage2)
        e.Cancel = true;
}

Eine andere Idee ist, alle Steuerelemente auf der Registerkarte in ein Bedienfeld-Steuerelement einzufügen und das Bedienfeld zu deaktivieren! Smiley

Sie können die Registerkarte auch aus der tabControl1.TabPages-Auflistung entfernen. Das würde die Registerkarte verbergen.

Credits gehen an littleguru @ Channel 9 .

Stormenet
quelle
Vollständiger und der Beitrag, den ich hätte veröffentlichen sollen :)
Martijn Laarman
Das ist eine verdammt brillante Lösung !!
Cornelius
13

Vermutlich möchten Sie die Registerkarte im Registersteuerelement sehen, aber Sie möchten, dass sie "deaktiviert" ist (dh grau und nicht auswählbar). Es gibt keine integrierte Unterstützung dafür, aber Sie können den Zeichenmechanismus überschreiben, um den gewünschten Effekt zu erzielen.

Ein Beispiel dafür finden Sie hier .

Die Magie liegt in diesem Ausschnitt aus der präsentierten Quelle und in der DisableTab_DrawItem-Methode:

this.tabControl1.DrawMode = TabDrawMode.OwnerDrawFixed;
this.tabControl1.DrawItem += new DrawItemEventHandler( DisableTab_DrawItem );
Stewart
quelle
1
Beispiellink scheint jetzt tot zu sein.
Narthring
1
@Narthring - Danke, ich habe den Link durch einen funktionierenden ersetzt.
Stewart
2
@Narthring Es ist wieder tot.
Sukasa
Dies ist die "echte" Antwort auf diese Frage. Es gibt eine Aufzeichnung des toten Links von waybackmachine: [ web.archive.org/web/20131102065816/http://… .
Joe Uhren
Eine Verbesserung dieser Antwort ... Fügen Sie jeder Ihrer Registerkarten einen EnabledChanged- Ereignishandler hinzu, und lassen Sie den Ereignishandler Invalidate () auf dem Registersteuerelement aufrufen . Auf diese Weise wird die Textfarbe automatisch aktualisiert.
ulatekh
12

Erweitern Sie die Antwort von Cédric Guillemette, nachdem Sie Folgendes deaktiviert haben Control:

((Control)this.tabPage).Enabled = false;

... Sie können dann der Griff TabControls‘ SelectingEreignis als:

private void tabControl_Selecting(object sender, TabControlCancelEventArgs e)
{
    e.Cancel = !((Control)e.TabPage).Enabled;
}
HF-Modulator
quelle
8

Dadurch wird die Registerkarte entfernt, Sie müssen sie jedoch bei Bedarf erneut hinzufügen:

tabControl1.Controls.Remove(tabPage2);

Wenn Sie es später benötigen, möchten Sie es möglicherweise vor dem Entfernen auf einer temporären Registerkarte speichern und bei Bedarf erneut hinzufügen.

Sahran
quelle
Ich denke, es funktioniert perfekt, wenn Sie beim Laden des Ereignisses des Formulars überprüfen möchten, ob der Benutzer berechtigt ist, auf diese Registerkarte zuzugreifen, und wenn nicht, entfernen Sie sie einfach ganz.
ThunderGr
5

Die einzige Möglichkeit besteht darin, das SelectingEreignis abzufangen und zu verhindern, dass eine Registerkarte aktiviert wird.

Martijn Laarman
quelle
2

Der schwierigste Weg ist, das übergeordnete Element auf null zu setzen (machen Sie den Tab allein ohne übergeordnetes Element):

 tabPage.Parent = null;

Und wenn Sie es zurückgeben möchten (wird es am Ende der Seitensammlung zurückgeben):

tabPage.Parent = tabControl;

Und wenn Sie es an einer bestimmten Stelle auf den Seiten zurückgeben möchten, können Sie Folgendes verwenden:

tabControl.TabPages.Insert(indexLocationYouWant, tabPage);
Amr Ashraf
quelle
1
Es funktioniert gut! :)..Ich habe eine Frage. Wenn wir es wieder in das Tabcontrol zurückbringen, wird der endgültige Index hinzugefügt. So fügen wir die Registerkarte von Anfang an am gleichen Index hinzu.
User6667769
1
Wenn Sie es an einem gewünschten Ort zurückgeben möchten (nicht am Ende), verwenden Sie: tabControl.TabPages.Insert (indexLocationYouWant, tabPage);
Amr Ashraf
1
Vielen Dank für Ihre Antwort @Amr Ashraf
User6667769
1

Ich musste vor einiger Zeit damit umgehen. Ich habe den Tab aus der TabPages-Sammlung entfernt (ich denke, das ist es) und ihn wieder hinzugefügt, als sich die Bedingungen geändert haben. Aber das war nur in Winforms, wo ich den Tab behalten konnte, bis ich ihn wieder brauchte.

jcollum
quelle
1

Sie können dies über die Registerkarten tun: tabPage1.Hide (), tabPage2.Show () usw.

Aldebaran
quelle
2
Ich habe es in Windows Ce 6.0 mit .net Compact Framework 3.5 verwendet und es hat funktioniert. Die Frage gibt keinen Hinweis auf die Plattform. Wo brauchen Sie das, Web oder Desktop oder Mobile?
Aldebaran
1

tabControl.TabPages.Remove (tabPage1);

Johannes Kawali
quelle
0

Ich habe in der Vergangenheit Registerkarten entfernt, um zu verhindern, dass der Benutzer darauf klickt. Dies ist jedoch wahrscheinlich nicht die beste Lösung, da sie möglicherweise sehen müssen, dass die Registerkarte vorhanden ist.

Aaron Smith
quelle
0

Mithilfe von Ereignissen und den Eigenschaften des Registersteuerelements können Sie aktivieren / deaktivieren, was Sie möchten, wann Sie möchten. Ich habe einen Bool verwendet, der für alle Methoden in der untergeordneten mdi-Formularklasse verfügbar ist, in der das tabControl verwendet wird.

Denken Sie daran, dass das Auswahlereignis jedes Mal ausgelöst wird, wenn auf eine Registerkarte geklickt wird. Für eine große Anzahl von Registerkarten ist ein "CASE" möglicherweise einfacher zu verwenden als eine Reihe von ifs.

public partial class Form2 : Form
    {
        bool formComplete = false;

        public Form2()
        {
            InitializeComponent();

        }

        private void button1_Click(object sender, EventArgs e)
        {


            formComplete = true;
            tabControl1.SelectTab(1);

        }

        private void tabControl1_Selecting(object sender, TabControlCancelEventArgs e)
        {
            if (tabControl1.SelectedTab == tabControl1.TabPages[1])
            {

                tabControl1.Enabled = false;

                if (formComplete)
                {
                    MessageBox.Show("You will be taken to next tab");
                    tabControl1.SelectTab(1);

                }
                else
                {
                    MessageBox.Show("Try completing form first");
                    tabControl1.SelectTab(0);
                }
                tabControl1.Enabled = true;
            }
        }
    }
KWB Tech
quelle
0

Ich habe dieses Problem folgendermaßen gelöst: Ich habe 3 Registerkarten und möchte den Benutzer auf der ersten Registerkarte belassen, wenn er sich nicht angemeldet hat, also auf dem SelectingEvent von TabControl, das ich geschrieben habe

if (condition) { TabControl.Deselect("2ndPage"); TabControl.Deselect("3dPage"); }
Orkhan M.
quelle
0

Der Benutzer kann nicht auf Registerkarten klicken, um zu navigieren, aber er kann die beiden Schaltflächen ( Nextund Back) verwenden. Der Benutzer kann nicht mit dem nächsten fortfahren, wenn die // Bedingungen nicht erfüllt sind.

private int currentTab = 0;

private void frmOneTimeEntry_Load(object sender, EventArgs e)
{
    tabMenu.Selecting += new TabControlCancelEventHandler(tabMenu_Selecting);
}

private void tabMenu_Selecting(object sender, TabControlCancelEventArgs e)
{
    tabMenu.SelectTab(currentTab);
}

private void btnNextStep_Click(object sender, EventArgs e)
{
    switch(tabMenu.SelectedIndex)
    {
        case 0:
            //if conditions met GoTo
        case 2:
            //if conditions met GoTo
        case n:
            //if conditions met GoTo
    {
    CanLeaveTab:
    currentTab++;
    tabMenu.SelectTab(tabMenu.SelectedIndex + 1);
    if (tabMenu.SelectedIndex == 3)
        btnNextStep.Enabled = false;
    if (btnBackStep.Enabled == false)
        btnBackStep.Enabled = true;

    CannotLeaveTab:
        ;
}

private void btnBackStep_Click(object sender, EventArgs e)
{
    currentTab--;
    tabMenu.SelectTab(tabMenu.SelectedIndex - 1);
    if (tabMenu.SelectedIndex == 0)
        btnBackStep.Enabled = false;
    if (btnNextStep.Enabled == false)
        btnNextStep.Enabled = true;
}
kennedy484
quelle
0

rfnodulator Antwort für Vb.Net:

Private Sub TabControl1_Selecting(sender As Object, e As TabControlCancelEventArgs) Handles TabControl1.Selecting
        e.Cancel = Not e.TabPage.Enabled
End Sub
Matias Masso
quelle
0

Angenommen, Sie haben diese Steuerelemente:

TabControl mit dem Namen tcExemple.

Registerkarten mit den Namen tpEx1 und tpEx2.

Versuch es:

Setzen Sie den DrawMode Ihrer TabPage auf OwnerDrawFixed. Stellen Sie nach InitializeComponent () sicher, dass tpEx2 nicht aktiviert ist, indem Sie diesen Code hinzufügen:

((Control)tcExemple.TabPages["tpEx2").Enabled = false;

Fügen Sie der Auswahl tcExemple den folgenden Code hinzu:

private void tcExemple_Selecting(object sender, TabControlCancelEventArgs e)
    {
        if (!((Control)e.TabPage).Enabled)
        {
            e.Cancel = true;
        }
    }

An DrawItem-Ereignis von tc anhängen Diesen Code anhängen:

private void tcExemple_DrawItem(object sender, DrawItemEventArgs e)
    {
        TabPage page = tcExemple.TabPages[e.Index];
        if (!((Control)page).Enabled)
        {
            using (SolidBrush brush = new SolidBrush(SystemColors.GrayText))
            {
                e.Graphics.DrawString(page.Text, page.Font, brush, e.Bounds);
            }
        }
        else
        {
            using (SolidBrush brush = new SolidBrush(page.ForeColor))
            {
                e.Graphics.DrawString(page.Text, page.Font, brush, e.Bounds);
            }
        }
    }

Dadurch wird die zweite Registerkarte nicht anklickbar.

Rafael
quelle
0

Dies ist eine alte Frage, aber jemand kann von meiner Hinzufügung profitieren. Ich brauchte ein TabControl, das nacheinander ausgeblendete Registerkarten anzeigt (nachdem eine Aktion auf der aktuellen Registerkarte ausgeführt wurde). Also habe ich eine schnelle Klasse zum Erben erstellt und HideSuccessive () beim Laden aufgerufen:

public class RevealingTabControl : TabControl
{
    private Action _showNextRequested = delegate { };

    public void HideSuccessive()
    {
        var tabPages = this.TabPages.Cast<TabPage>().Skip(1);
        var queue = new ConcurrentQueue<TabPage>(tabPages);
        tabPages.ToList().ForEach(t => t.Parent = null);
        _showNextRequested = () =>
        {
            if (queue.TryDequeue(out TabPage tabPage))
                tabPage.Parent = this;
        };
    }

    public void ShowNext() => _showNextRequested();
}
Ryan Naccarato
quelle
-1

Wenn wir this.tabpage.PageEnabled = falseim Formularladeereignis schreiben , wird die Registerkarte deaktiviert.

Neu
quelle
Kann diese Eigenschaft nicht sehen
John
Bitte überprüfen Sie, ob Sie es im Ladeereignis des Formulars versucht haben.
Neu
Nur doppelt geprüft jetzt überprüft. Kann es nicht sehen.
John
Bitte überprüfen Sie, ob Sie dies verwendet haben: private void XtraForm1_Load (Objektabsender, EventArgs e) {this.xtraTabPage1.PageEnabled = false; } das XtraForm1 ist das DevExpress XtraForm und die Registerkarte xtraTabPage ist DevExpress XtraTabpage
Neu
Warum haben Sie in Ihrer ursprünglichen Antwort nichts über DevExpress gesagt ...?
John
-1

Verwenden:

 tabControl1.TabPages[1].Enabled = false;

Durch das Schreiben dieses Codes wird die Registerkarte nicht vollständig deaktiviert (kann nicht ausgewählt werden), aber der interne Inhalt wird deaktiviert, was Ihrer Meinung nach Ihren Anforderungen entspricht.

Code_Worm
quelle
-1

Die Lösung ist sehr einfach.

Diese Zeile entfernen / kommentieren

this.tabControl.Controls.Add(this.YourTabName);

in der IntializeComponent () -Methode in MainForm.cs


quelle
-1

Ich konnte keine passende Antwort auf die Frage finden. Es scheint keine Lösung zu geben, um die bestimmte Registerkarte zu deaktivieren. Was ich getan habe, ist, die spezifische Registerkarte an eine Variable zu übergeben und sie im SelectedIndexChangedEreignis zurückzusetzen auf SelectedIndex:

//variable for your specific tab 
int _TAB = 0;

//here you specify your tab that you want to expose
_TAB = 1;
tabHolder.SelectedIndex = _TAB;

private void tabHolder_SelectedIndexChanged(object sender, EventArgs e)
{
    if (_TAB != 0) tabHolder.SelectedIndex = _TAB;
}

Sie deaktivieren die Registerkarte also nicht wirklich, aber wenn Sie auf eine andere Registerkarte klicken, kehren Sie immer zur ausgewählten Registerkarte zurück.

Andy
quelle
-2
MyTabControl.SelectedTab.Enabled = false;
jay_t55
quelle