Jak mogę wyłączyć zakładkę w TabControl?

Odpowiedzi:

71

Tabpage klasa ukrywa Enabled właściwość. To było zamierzone, ponieważ występuje z nim niezręczny problem z projektem interfejsu użytkownika. Podstawowym problemem jest to, że wyłączenie strony nie wyłącza również zakładki. A jeśli spróbujesz obejść ten problem, wyłączając kartę ze zdarzeniem Selecting, to nie zadziała, gdy TabControl ma tylko jedną stronę.

Jeśli te problemy z użytecznością nie dotyczą Ciebie, pamiętaj, że właściwość nadal działa, jest po prostu ukryta przed IntelliSense. Jeśli FUD jest niewygodny, możesz po prostu zrobić to:

public static void EnableTab(TabPage page, bool enable) {
    foreach (Control ctl in page.Controls) ctl.Enabled = enable;
}
Hans Passant
źródło
3
Zastanawiam się, jaka jest historia z tyłu, gdy nie pozwalałem na przełączanie widoczności zakładek
Shashank Shekhar
91

Prześlij TabPage na Control, a następnie ustaw właściwość Enabled na false.

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

Dlatego nagłówek zakładki będzie nadal włączony, ale jego zawartość będzie wyłączona.

Cédric Guillemette
źródło
3
Myślę, że to mija się z celem wyłączenia samej karty. Użytkownik nie powinien mieć możliwości jej wybrania i przeglądania zawartości.
ThunderGr,
3
To może być twój przypadek użycia, ale myślę, że jest to przydatne, jeśli karta musi być tylko do odczytu z powodu pewnych praw.
Cédric Guillemette
9
Po co downcasting TabPage to Control? Możemy wywołać właściwość Enabled z TabPage ze względu na polimorfizm.
Eldar Agalarov
1
Nie jestem pewien, czy kiedykolwiek było inaczej, ale dziś jest to kompletny nonsens. 69 zwolenników poparcia w błędzie.
Oj
1
@TaW To pytanie konkretnie i zwięźle odpowiada na pytanie. „Czy istnieje sposób na wyłączenie karty w kontrolce tabulacji?” Nie pytają, jak ukryć kartę. 69 pozytywnych głosów po prawej stronie ... 1 komentator, który nie przeczytał źle pytania.
Oj
70

Możesz po prostu użyć:

tabPage.Enabled = false;

Ta właściwość nie jest pokazana, ale działa bez żadnych problemów.

Zdarzenie Selecting można zaprogramować tak, TabControleraby nie było możliwe przejście do nieedytowalnej zakładki:

private void tabControler_Selecting(object sender, TabControlCancelEventArgs e)
{
    if (e.TabPageIndex < 0) return;
    e.Cancel = !e.TabPage.Enabled;
}
Lecsox
źródło
3
Jakie to dziwne… wydaje się to również odnosić do Visiblewłaściwości, chociaż nie wydawało się, aby miało to żaden efekt wizualny, kiedy ją testowałem.
Alfie
@Alfie Jego, ponieważ TabPage dziedziczy z następującej hierarchii: Control> ScrollableControl> Panel> TabPage, zachowanie Enable, Visible itp. Jest polimorficzne.
Master Yoda
50

Możesz zarejestrować zdarzenie „Selecting” i anulować nawigację do strony zakładki:

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

Innym pomysłem jest umieszczenie wszystkich kontrolek na karcie w kontrolce panelu i wyłączenie panelu! Smiley

Możesz także usunąć tabpage z kolekcji tabControl1.TabPages. To by ukryło zakładkę.

Kredyty trafiają do littleguru @ Channel 9 .

Stormenet
źródło
Bardziej kompletny i post, który powinienem był zamieścić :)
Martijn Laarman
To cholernie genialne rozwiązanie!
Cornelius
13

Przypuszczalnie chcesz widzieć kartę w kontrolce karty, ale chcesz, aby była „wyłączona” (tj. Wyszarzona i niewybieralna). Nie ma wbudowanej obsługi tego, ale możesz zastąpić mechanizm rysowania, aby uzyskać pożądany efekt.

Przykładem, jak to zrobić jest warunkiem tutaj .

Magia tkwi w tym fragmencie z prezentowanego źródła oraz w metodzie DisableTab_DrawItem:

this.tabControl1.DrawMode = TabDrawMode.OwnerDrawFixed;
this.tabControl1.DrawItem += new DrawItemEventHandler( DisableTab_DrawItem );
Stewart
źródło
1
Przykładowy link wydaje się teraz martwy.
Narthring
1
@Narthring - Dzięki, podmieniłem link na działający.
Stewart
2
@Narthring Znów jest martwy.
Sukasa,
To jest „prawdziwa” odpowiedź na to pytanie. Istnieje zapis niedziałającego linku z waybackmachine: [ web.archive.org/web/20131102065816/http://… .
Joe Uhren
Jedna poprawa tej odpowiedzi ... dodaj EnabledChanged zdarzeń obsługi do każdej karty i mieć wywołanie procedury obsługi zdarzeń unieważnić () na karcie-kontrola. W ten sposób kolor tekstu zaktualizuje się automatycznie.
ulatekh
12

Rozszerzanie na odpowiedź Cédrica Guillemette, po wyłączeniu Control:

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

... możesz wtedy obsłużyć zdarzenie TabControl' Selectingjako:

private void tabControl_Selecting(object sender, TabControlCancelEventArgs e)
{
    e.Cancel = !((Control)e.TabPage).Enabled;
}
rfmodulator
źródło
8

Spowoduje to usunięcie strony karty, ale w razie potrzeby będziesz musiał dodać ją ponownie:

tabControl1.Controls.Remove(tabPage2);

Jeśli będziesz go później potrzebować, możesz zechcieć go przechowywać na tymczasowej karcie przed usunięciem, a następnie ponownie dodać w razie potrzeby.

sahran
źródło
Myślę, że działa to doskonale, gdy chcesz sprawdzić, w zdarzeniu Load formularza, czy użytkownik ma dostęp do tej karty, a jeśli nie, po prostu ją całkowicie usuń.
ThunderGr,
5

Jedynym sposobem jest złapanie Selectingzdarzenia i zapobieżenie aktywacji karty.

Martijn Laarman
źródło
2

Najtrudniejszym sposobem jest uczynienie jego rodzica równym null (zrób samą tabulator bez rodzica):

 tabPage.Parent = null;

A kiedy zechcesz go zwrócić (zwróci go z powrotem na końcu zbioru stron):

tabPage.Parent = tabControl;

A jeśli chcesz zwrócić go z powrotem w określonej lokalizacji wśród stron, których możesz użyć:

tabControl.TabPages.Insert(indexLocationYouWant, tabPage);
Amr Ashraf
źródło
1
Działa dobrze! :)..Mam jedno pytanie. Kiedy wrócimy z powrotem do tabcontrol, dodamy ostateczny indeks. Jak dodać zakładkę w tym samym indeksie od jej początkowego etapu.
User6667769
2
Jeśli chcesz zwrócić go z powrotem w wybranej lokalizacji (nie na końcu), użyj: tabControl.TabPages.Insert (indexLocationYouWant, tabPage);
Amr Ashraf
1
Dziękuję za odpowiedź @Amr Ashraf
User6667769
1

Musiałem sobie z tym poradzić jakiś czas temu. Usunąłem kartę z kolekcji TabPages (myślę, że to wszystko) i dodałem ją z powrotem, gdy zmieniły się warunki. Ale to było tylko w Winforms, gdzie mogłem zachować tę zakładkę, dopóki nie będę jej ponownie potrzebować.

jcollum
źródło
1

Możesz to zrobić poprzez zakładki: tabPage1.Hide (), tabPage2.Show () itd.

aldebaran
źródło
2
Użyłem go w systemie Windows CE 6.0 z .NET Compact Framework 3.5 i działało. Pytanie nie daje żadnej wskazówki na temat platformy. Gdzie to jest potrzebne, w sieci, na komputerze lub w telefonie komórkowym?
aldebaran
1

tabControl.TabPages.Remove (tabPage1);

Johannes Kawali
źródło
0

W przeszłości usuwałem karty, aby użytkownik nie mógł ich klikać. Prawdopodobnie nie jest to jednak najlepsze rozwiązanie, ponieważ może być konieczne sprawdzenie, czy strona karty istnieje.

Aaron Smith
źródło
0

Korzystając ze zdarzeń i właściwości kontrolki karty, możesz włączać / wyłączać to, co chcesz, kiedy chcesz. Użyłem jednego bool, który jest dostępny dla wszystkich metod w klasie formularza potomnego mdi, w której jest używany tabControl.

Pamiętaj, że zdarzenie wybierania jest uruchamiane za każdym razem, gdy klikniesz dowolną kartę. W przypadku dużej liczby kart „CASE” może być łatwiejsze w użyciu niż kilka „if”.

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
źródło
0

Rozwiązałem ten problem w ten sposób: mam 3 zakładki i chcę zachować użytkownika na pierwszej karcie, jeśli się nie zalogował, więc na SelectingEvent z TabControl napisałem

if (condition) { TabControl.Deselect("2ndPage"); TabControl.Deselect("3dPage"); }
Orkhan M.
źródło
0

Użytkownik nie może klikać kart, aby nawigować, ale może użyć dwóch przycisków ( Nexti Back). Użytkownik nie może przejść do następnej, jeśli warunki // nie są spełnione.

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
źródło
0

Załóżmy, że masz te kontrolki:

TabControl o nazwie tcExemple.

TabPages o nazwach tpEx1 i tpEx2.

Spróbuj:

Ustaw DrawMode swojej TabPage na OwnerDrawFixed; Po InitializeComponent () upewnij się, że tpEx2 nie jest włączony, dodając ten kod:

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

Dodaj do zdarzenia tcExemple zaznaczenie poniższy kod:

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

Dołącz do zdarzenia DrawItem w tcExemple ten kod:

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);
            }
        }
    }

Spowoduje to, że druga karta nie będzie możliwa do kliknięcia.

Rafael
źródło
0

To stare pytanie, ale ktoś może skorzystać na moim uzupełnieniu. Potrzebowałem TabControl, który wyświetlałby ukryte karty sukcesywnie (po wykonaniu akcji na bieżącej karcie). Utworzyłem więc szybką klasę do dziedziczenia i wywołałem HideSuccessive () podczas ładowania:

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
źródło
0

w języku C # 7.0 dostępna jest nowa funkcja o nazwie Dopasowywanie wzorców . Możesz wyłączyć wszystkie karty za pomocą wzorca typu .

foreach (Control control in Controls)
{
    // the is expression tests the variable and 
    // assigned it to a new appropriate variable type
    if (control is TabControl tabs)
    {
        tabs.Enabled = false;
    }
}
Umut D.
źródło
-1

W przypadku ładowania formularza, jeśli napiszemy this.tabpage.PageEnabled = false, zakładka zostanie wyłączona.

Nowy
źródło
Nie widzę tej nieruchomości
Jan
proszę sprawdzić, czy próbowałeś tego w przypadku ładowania formularza?
Nowy
Właśnie dwukrotnie sprawdzone. Nie widzę.
John
sprawdź, czy użyłeś tego: private void XtraForm1_Load (nadawca obiektu, EventArgs e) {this.xtraTabPage1.PageEnabled = false; } XtraForm1 to DevExpress XtraForm, a zakładka xtraTabPage to DevExpress XtraTabpage
Nowość
Dlaczego w swojej oryginalnej odpowiedzi nie powiedziałeś nic o DevExpress ...?
John
-1

Posługiwać się:

 tabControl1.TabPages[1].Enabled = false;

Pisząc ten kod, strona zakładki nie zostanie całkowicie wyłączona (nie będzie można wybrać), ale jej zawartość wewnętrzna zostanie wyłączona, co moim zdaniem zaspokoi Twoje potrzeby.

Code_Worm
źródło
-1

Rozwiązanie jest bardzo proste.

Usuń / skomentuj tę linię

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

w metodzie IntializeComponent () w pliku MainForm.cs


źródło
-1

Nie mogłem znaleźć odpowiedniej odpowiedzi na to pytanie. Wygląda na to, że nie ma rozwiązania umożliwiającego wyłączenie określonej karty. To, co zrobiłem, to przekazanie określonej zakładki do zmiennej i na SelectedIndexChangedwypadek gdyby umieściłem ją z powrotem 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;
}

Tak więc w rzeczywistości nie wyłączasz karty, ale po kliknięciu innej karty zawsze powraca do wybranej karty.

Andy
źródło
-2
MyTabControl.SelectedTab.Enabled = false;
jay_t55
źródło