¿Cómo puedo desactivar una pestaña dentro de un TabControl?

Respuestas:

71

La clase TabPage oculta la propiedad Enabled. Eso fue intencional, ya que hay un problema de diseño de interfaz de usuario incómodo. El problema básico es que deshabilitar la página no también deshabilita la pestaña. Y si intenta solucionarlo deshabilitando la pestaña con el evento Selecting, entonces no funciona cuando TabControl tiene solo una página.

Si estos problemas de usabilidad no le preocupan, tenga en cuenta que la propiedad aún funciona, simplemente está oculta a IntelliSense. Si el FUD es incómodo, simplemente puede hacer esto:

public static void EnableTab(TabPage page, bool enable) {
    foreach (Control ctl in page.Controls) ctl.Enabled = enable;
}
Hans Passant
fuente
3
Me pregunto cuál es la historia de fondo para no permitir alternar la visibilidad de la pestaña
Shekhar
91

Transmita su TabPage a un Control, luego establezca la propiedad Enabled en false.

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

Por lo tanto, el encabezado de la pestaña seguirá estando habilitado pero su contenido estará deshabilitado.

Cédric Guillemette
fuente
3
Creo que esto pierde el punto de deshabilitar la pestaña en sí. No se supone que el usuario pueda seleccionarlo y ver el contenido.
ThunderGr
3
Ese puede ser su caso de uso, pero creo que es útil si la pestaña necesita ser de solo lectura debido a algunos derechos.
Cédric Guillemette
9
¿Por qué es necesario reducir TabPage a Control? Podemos invocar la propiedad Enabled desde TabPage debido al polimorfismo.
Eldar Agalarov
1
No estoy seguro si alguna vez fue diferente, pero hoy es una tontería total. 69 votantes positivos en el error. Ouch ..
TaW
1
@TaW Esta pregunta responde de manera específica y concisa a la pregunta. "¿Hay alguna forma de deshabilitar una pestaña en un control de pestañas?" No preguntan cómo ocultar una pestaña. 69 votantes positivos en la derecha ... 1 comentarista que no leyó la pregunta mal. Ay ...
DDuffy
70

Simplemente puede usar:

tabPage.Enabled = false;

Esta propiedad no se muestra, pero funciona sin problemas.

Puede programar el evento de selección TabControlerpara que sea imposible cambiar a una pestaña no editable:

private void tabControler_Selecting(object sender, TabControlCancelEventArgs e)
{
    if (e.TabPageIndex < 0) return;
    e.Cancel = !e.TabPage.Enabled;
}
Lecsox
fuente
3
Qué extraño ... esto también parece ser cierto para la Visiblepropiedad, aunque no pareció tener ningún efecto visual cuando la probé.
Alfie
@Alfie Es porque TabPage hereda de la siguiente jerarquía: Control> ScrollableControl> Panel> TabPage, el comportamiento Habilitar, Visible, etc. es polimórfico.
Maestro Yoda
49

Puede registrar el evento "Seleccionar" y cancelar la navegación a la página de la pestaña:

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

Otra idea es poner todos los controles en la pestaña en un panel de control y deshabilitar el panel. Smiley

También puede eliminar la pestaña de la colección tabControl1.TabPages. Eso ocultaría la pestaña.

Los créditos van a littleguru @ Channel 9 .

Stormenet
fuente
Más completa y la publicación que debería haber publicado :)
Martijn Laarman
¡Esta es una solución increíblemente brillante!
Cornelius
13

Presumiblemente, desea ver la pestaña en el control de pestañas, pero desea que esté "deshabilitada" (es decir, atenuada y no seleccionable). No hay soporte incorporado para esto, pero puede anular el mecanismo de dibujo para obtener el efecto deseado.

Aquí se proporciona un ejemplo de cómo hacer esto .

La magia está en este fragmento de la fuente presentada y en el método DisableTab_DrawItem:

this.tabControl1.DrawMode = TabDrawMode.OwnerDrawFixed;
this.tabControl1.DrawItem += new DrawItemEventHandler( DisableTab_DrawItem );
Stewart
fuente
1
El enlace de ejemplo ahora parece estar muerto.
Narthring
1
@Narthring - Gracias, he sustituido el enlace por uno que funciona.
Stewart
2
@Narthring Está muerto de nuevo.
Sukasa
Esta es la respuesta "real" a esta pregunta. Hay un registro del enlace muerto de waybackmachine: [ web.archive.org/web/20131102065816/http://… .
Joe Uhren
Una mejora a esta respuesta ... agregue un controlador de eventos EnabledChanged a cada una de sus pestañas y haga que el controlador de eventos llame a Invalidate () en el control de pestañas. De esa forma, el color del texto se actualizará automáticamente.
ulatekh
12

Ampliando la respuesta de Cédric Guillemette, después de desactivar Control:

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

... a continuación, puede manejar el TabControl's Selectingevento como:

private void tabControl_Selecting(object sender, TabControlCancelEventArgs e)
{
    e.Cancel = !((Control)e.TabPage).Enabled;
}
modulador de rf
fuente
8

Esto eliminará la página de la pestaña, pero deberá volver a agregarla cuando la necesite:

tabControl1.Controls.Remove(tabPage2);

Si lo va a necesitar más adelante, es posible que desee almacenarlo en una pestaña temporal antes de eliminarlo y luego volver a agregarlo cuando sea necesario.

saherán
fuente
Creo que funciona perfectamente cuando desea verificar, en el evento Load del formulario, si el usuario es elegible para acceder a esta pestaña y, si no, simplemente elimínela por completo.
ThunderGr
5

La única forma es detectar el Selectingevento y evitar que se active una pestaña.

Martijn Laarman
fuente
2

La forma más complicada es hacer que su padre sea igual a nulo (haga que la pestaña solo sin el padre):

 tabPage.Parent = null;

Y cuando quiera devolverlo (lo devolverá al final de la colección de páginas):

tabPage.Parent = tabControl;

Y si desea devolverlo en una ubicación específica entre las páginas, puede usar:

tabControl.TabPages.Insert(indexLocationYouWant, tabPage);
Amr Ashraf
fuente
1
¡Está funcionando bien! :)..Tengo una pregunta. Cuando lo devolvemos a la pestaña, controla su índice final agregado. Cómo agregar la página de pestañas en el mismo índice desde su etapa inicial.
User6667769
1
Si desea devolverlo en una ubicación que desee (no al final), use: tabControl.TabPages.Insert (indexLocationYouWant, tabPage);
Amr Ashraf
1
Gracias por su respuesta @Amr Ashraf
User6667769
1

Tuve que manejar esto hace un tiempo. Eliminé la pestaña de la colección TabPages (creo que eso es todo) y la agregué cuando las condiciones cambiaron. Pero eso fue solo en Winforms donde pude mantener la pestaña hasta que la necesite nuevamente.

jcollum
fuente
1

Puede hacerlo a través de las pestañas: tabPage1.Hide (), tabPage2.Show () etc.

aldebarán
fuente
2
Lo usé en windows ce 6.0 con .net compact framework 3.5 y estaba funcionando. La pregunta no da ninguna pista sobre la plataforma. ¿Dónde lo necesitas, web, de escritorio o móvil?
aldebarán
1

tabControl.TabPages.Remove (tabPage1);

Johannes Kawali
fuente
0

Eliminé páginas con pestañas en el pasado para evitar que el usuario haga clic en ellas. Sin embargo, probablemente esta no sea la mejor solución porque es posible que necesiten ver que existe la página de pestañas.

Aaron Smith
fuente
0

Usando eventos y las propiedades del control de pestañas, puede habilitar / deshabilitar lo que desee cuando lo desee. Usé un bool que está disponible para todos los métodos en la clase de formulario secundario mdi donde se usa tabControl.

Recuerde que el evento de selección se activa cada vez que se hace clic en cualquier pestaña. Para un gran número de pestañas, un "CASO" puede ser más fácil de usar que un montón de si.

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;
            }
        }
    }
Tecnología KWB
fuente
0

He resuelto este problema de esta manera: tengo 3 pestañas y quiero mantener al usuario en la primera pestaña si no inició sesión, así que en el evento de selección de TabControl escribí

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

El usuario no puede hacer clic en las pestañas para navegar, pero puede usar los dos botones ( Nexty Back). El usuario no puede continuar con el siguiente si no se cumplen // las condiciones.

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
fuente
0

Respuesta de rfnodulator para 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
fuente
0

Suponga que tiene estos controles:

TabControl con el nombre tcExemple.

TabPages con los nombres tpEx1 y tpEx2.

Intentalo:

Establezca DrawMode de su TabPage en OwnerDrawFixed; Después de InitializeComponent (), asegúrese de que tpEx2 no esté habilitado agregando este código:

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

Agregue al evento de selección tcExemple el siguiente código:

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

Adjuntar al evento DrawItem de tc Ejemplo de este código:

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

Hará que no se pueda hacer clic en la segunda pestaña.

Rafael
fuente
0

Esta es una vieja pregunta, pero alguien puede beneficiarse de mi adición. Necesitaba un TabControl que mostrara las pestañas ocultas sucesivamente (después de realizar una acción en la pestaña actual). Entonces, hice una clase rápida para heredar y llamé a HideSuccessive () en Load:

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
fuente
-1

En el evento de carga de formulario si escribimos this.tabpage.PageEnabled = false, la pestaña se desactivará.

Nuevo
fuente
No puedo ver esa propiedad
Juan
por favor, verifique si lo probó en el evento de carga del formulario.
Nuevo
Solo comprobado dos veces ahora. No puedo verlo.
John
compruebe si utilizó esto: private void XtraForm1_Load (remitente del objeto, EventArgs e) {this.xtraTabPage1.PageEnabled = false; } el XtraForm1 es DevExpress XtraForm y la pestaña xtraTabPage es DevExpress XtraTabpage
Nuevo
¿Por qué no dijiste nada sobre DevExpress en tu respuesta original ...?
John
-1

Utilizar:

 tabControl1.TabPages[1].Enabled = false;

Al escribir este código, la página de la pestaña no se desactivará por completo (no se podrá seleccionar), pero su contenido interno se desactivará, lo que creo que satisface sus necesidades.

Code_Worm
fuente
-1

La solución es muy simple.

Eliminar / comentar esta línea

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

en el método IntializeComponent () en MainForm.cs


fuente
-1

No pude encontrar una respuesta adecuada a la pregunta. Parece que no hay solución para deshabilitar la pestaña específica. Lo que hice fue pasar la pestaña específica a una variable y, en el SelectedIndexChangedcaso, volver a colocarla en 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;
}

Por lo tanto, en realidad no deshabilita la pestaña, pero cuando se hace clic en otra pestaña, siempre regresa a la pestaña seleccionada.

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