2009-08-24 25 views
7

Necesito determinar de qué pestaña viene el usuario, y cuándo, cuando cambian las pestañas, y posiblemente cancelar el cambio. He intentado anular la selección, deseleccionar, seleccionar, eventos seleccionados, y todos ellos muestran que e.TabPageIndex es lo mismo que el remitente. SelectedIndex.¿Cómo puedo saber a qué pestaña se desplaza de/a en un control de pestaña WinForms?

¿Hay algún evento, o propiedad, que pueda usar para poder determinar ambos lados de esto, o tengo que hackear algo junto con el almacenamiento en caché de un evento y usando ese valor en el nuevo evento.

Estoy tratando de evitar el manejo de los eventos Deseleccionar/Deseleccionar y el almacenamiento en caché del valor para usar en el evento Seleccionar. Ya sé que puedo hacer esto, así que estoy preguntando si hay una manera más limpia, sin hacer esto.

Lo he probado en C# y VB, con los mismos resultados (no es sorpresa).

Gracias.

Respuesta

7

No parece que ningún argumento de evento contenga los detalles de las pestañas anteriores y actuales, por lo que deberá controlar un par de eventos para realizar un seguimiento.

Como mínimo, debe usar el evento Deselected para almacenar una referencia a la pestaña seleccionada previamente. Siempre puede consultar TabControl para su pestaña actual. Para estirar un poco más, también puede manejar el evento Selected para rastrear la pestaña actual.

Option Strict On 
Option Explicit On 

Public Class Form1 

    Private PreviousTab As TabPage 
    Private CurrentTab As TabPage 

    Private Sub TabControl1_Deselected(ByVal sender As Object, ByVal e As System.Windows.Forms.TabControlEventArgs) Handles TabControl1.Deselected 
     PreviousTab = e.TabPage 
     Debug.WriteLine("Deselected: " + e.TabPage.Name) 
    End Sub 

    Private Sub TabControl1_Selected(ByVal sender As Object, ByVal e As System.Windows.Forms.TabControlEventArgs) Handles TabControl1.Selected 
     CurrentTab = e.TabPage 
     Debug.WriteLine("Selected: " + e.TabPage.Name) 
    End Sub 

    Private Sub TabControl1_Selecting(ByVal sender As Object, ByVal e As System.Windows.Forms.TabControlCancelEventArgs) Handles TabControl1.Selecting 
     If CurrentTab Is Nothing Then Return 
     Debug.WriteLine(String.Format("Proposed change from {0} to {1}", CurrentTab.Name, e.TabPage.Name)) 
    End Sub 

End Class 
+0

Sí, esa es la solución que tengo, pero estoy tratando de evitar hacer eso. Además, necesito usar el evento Seleccionar, para poder cancelar, pero eso está al lado del punto. –

+0

@Rick: no se parece al stock. WinForms TabControl es compatible con todo lo que está buscando, puede ampliarlo para proporcionar la información que está buscando, o puede utilizar un tercero Control de Tab (creo que Infragistics admite el comportamiento que estamos viendo) – STW

1

Puede suscribirse a TabControl.Deselecting. Cuando se activa, el índice de pestañas en el evento args será el índice anterior.

Puede suscribirse a TabControl.Selected. Cuando se activa este evento, el índice de pestañas será el índice de la pestaña recién seleccionada.

+0

Sí, estoy tratando de evitar tener que almacenar en caché el valor de esta manera. Parece que esta es la única manera sin embargo. –

+0

Sí. No hay un solo evento que tenga ambos índices de pestañas disponibles, desafortunadamente. –

1

Usted puede obtener el índice de la pestaña el usuario se aleja de con el evento anulación de la selección y almacenarlo en una variable para su uso posterior:

Private Sub TabControl1_Deselecting(ByVal sender As System.Object, ByVal e As System.Windows.Forms.TabControlCancelEventArgs) Handles TabControl1.Deselecting 
    someClassLevelVariable = e.TabPageIndex 
End Sub 

¿Quieres código de poner a evitar que el interruptor en el evento de selección. He aquí un ejemplo en VB.NET que le impide seleccionar la pestaña 2 en un control de ficha:

Private Sub TabControl1_Selecting(ByVal sender As System.Object, ByVal e As System.Windows.Forms.TabControlCancelEventArgs) Handles TabControl1.Selecting 
    If (e.TabPageIndex = 1) Then 
     e.Cancel = True 
    End If 
End Sub 
+0

Esto realmente no ayuda, sin embargo, ya que quiero saber la pestaña anterior antes de decidir si cancelar o no. –

+0

Actualicé mi respuesta, pero luego leí en otro comentario que no desea tener que almacenar en caché el valor de la pestaña actual. No sé de ninguna otra manera. – raven

1

que podría hacer algo así:

private int _oldIndex = -1; 

    private void tabControl1_Deselected(object sender, TabControlEventArgs e) 
    { 
     _oldIndex = e.TabPageIndex; 
    } 

    private void tabControl1_Selecting(object sender, TabControlCancelEventArgs e) 
    { 
     if (_oldIndex != -1) 
     { 
      if (CanChangeTab(_oldIndex, e.TabPageIndex)) 
      { 
       e.Cancel = true; 
      } 
     } 
    } 

    private bool CanChangeTab(int fromIndex, int toIndex) 
    { 
     // Put your logic here 
    } 
2

creo la bandera en el e.Cancel seleccionar evento debería hacer este truco. Esto envía la ficha seleccionada de nuevo a la original en cancelar:

private void tabControl1_Selecting(object sender, TabControlCancelEventArgs e) 
    { 
     int badIndex = 0; 

     if (tabControl1.SelectedIndex == badIndex) 
      e.Cancel = true;    
    } 

Si realmente necesita beharvior más compleja, la subclasificación de la tarjeta de registro funcionará, a continuación, reemplazar el método OnSelecting. Esto no debe hacerse a la ligera. Si el control se cambia en el futuro, tendrá un código roto. Y debe confirmar que todo el comportamiento del control de tabulación se cumple (es decir, constructores ...)

EDITAR: según los comentarios. Esto rastreará internamente la pestaña original antes de la selección.

public class MyTab : System.Windows.Forms.TabControl 
{ 
    int _previousTab; 

    protected override void OnSelecting(TabControlCancelEventArgs e) 
    { 
     // Some logic here to do cool UI things, perhaps use _previousTab 

     // Call the base method 
     base.OnSelecting(e);   
    } 
    protected override void OnDeselecting(TabControlCancelEventArgs e) 
    { 
     // Store the value for use later in the chain of events 
     _previousTab = this.SelectedIndex; 

     // Call the base method 
     base.OnDeselecting(e); 
    } 

} 
+0

Esto no hace nada para resolver el problema real, donde necesito saber de qué pestaña vienes. Heredar del control tampoco resolverá el problema, desafortunadamente. –

1

Para proporcionar una alternativa a mi respuesta inicial ....Aquí hay una muestra de un TabControl extendido que modifica los argumentos del evento para incluir más detalles.

Descargo de responsabilidad Esto se pega, ¡necesitará algunos ajustes con seguridad!

Option Strict On 
Option Explicit On 

Imports System 
Imports System.Windows.Forms 

Public Class ExtendedTabControl 
    Inherits TabControl 

    Public Shadows Event Selecting As EventHandler(Of SelectedTabChangingEventArgs) 
    Public Shadows Event Selected As EventHandler(Of SelectedTabChangedEventArgs) 

    Private _PreviousTab As TabPage 
    Public Property PreviousTab() As TabPage 
     Get 
      Return _PreviousTab 
     End Get 
     Private Set(ByVal value As TabPage) 
      _PreviousTab = value 
     End Set 
    End Property 

    Private _CurrentTab As TabPage 
    Public Property CurrentTab() As TabPage 
     Get 
      Return _CurrentTab 
     End Get 
     Private Set(ByVal value As TabPage) 
      _CurrentTab = value 
     End Set 
    End Property 

    Protected Overrides Sub OnDeselected(ByVal e As System.Windows.Forms.TabControlEventArgs) 
     PreviousTab = e.TabPage 
     MyBase.OnDeselected(e) 
    End Sub 

    Protected Overrides Sub OnSelected(ByVal e As System.Windows.Forms.TabControlEventArgs) 
     CurrentTab = e.TabPage 
     Dim selectedArgs As New SelectedTabChangedEventArgs(e, PreviousTab) 
     RaiseEvent Selected(Me, selectedArgs) 
    End Sub 

    Protected Overrides Sub OnSelecting(ByVal e As System.Windows.Forms.TabControlCancelEventArgs) 
     Dim selectedArgs As New SelectedTabChangingEventArgs(e, CurrentTab) 
     RaiseEvent Selecting(Me, selectedArgs) 
    End Sub 

End Class 

Public Class SelectedTabChangingEventArgs 
    Inherits TabControlCancelEventArgs 

    Public Sub New(ByVal selectingEventArgs As TabControlCancelEventArgs, ByVal previousTabPage As TabPage) 
     MyBase.New(selectingEventArgs.TabPage, selectingEventArgs.TabPageIndex, selectingEventArgs.Cancel, selectingEventArgs.Action) 
     Me.CurrentTab = previousTabPage 
    End Sub 

    Private _CurrentTab As TabPage 
    Public Property CurrentTab() As TabPage 
     Get 
      Return _CurrentTab 
     End Get 
     Set(ByVal value As TabPage) 
      _CurrentTab = value 
     End Set 
    End Property 

End Class 

Public Class SelectedTabChangedEventArgs 
    Inherits TabControlEventArgs 

    Public Sub New(ByVal selectedEventArgs As TabControlEventArgs, ByVal previousTabPage As TabPage) 
     MyBase.New(selectedEventArgs.TabPage, selectedEventArgs.TabPageIndex, selectedEventArgs.Action) 
     Me.PreviousTab = previousTabPage 
    End Sub 

    Private _PreviousTab As TabPage 
    Public Property PreviousTab() As TabPage 
     Get 
      Return _PreviousTab 
     End Get 
     Set(ByVal value As TabPage) 
      _PreviousTab = value 
     End Set 
    End Property 

End Class 

... y un Formulario de muestra usando este control ...

Option Strict On 
Option Explicit On 

Public Class Form1 

    Private Sub TabControl1_Selecting(ByVal sender As Object, ByVal e As SelectedTabChangingEventArgs) Handles TabControl1.Selecting 
     If e.CurrentTab Is Nothing Then Return 
     Console.WriteLine(String.Format("Proposed change from {0} to {1}", e.CurrentTab.Name, e.TabPage.Name)) 
    End Sub 

    Private Sub TabControl1_Selected(ByVal sender As Object, ByVal e As SelectedTabChangedEventArgs) Handles TabControl1.Selected 
     Console.WriteLine(String.Format("Changed from {0} to {1}", e.PreviousTab.Name, e.TabPage.Name)) 
    End Sub 

End Class 
+0

Desafortunadamente, no puedo sombrear los eventos, porque se pasa como System.Windows.Forms.Tabcontrol a otros métodos. Agradezco las respuestas, pero parece que mi conculsion inicial fue correcta. –

+0

@Rick: It * might * puede funcionar porque los tipos de evento sombreados amplían los tipos utilizados por el tipo base; los métodos que funcionan con él como un TabControl simplemente no verían las propiedades adicionales. – STW

+0

El código en el que se está usando esto es un marco para admitir a otros desarrolladores, por lo que estoy un poco limitado en lo que puedo hacer sin romper el código existente. Gracias de nuevo por sus respuestas. –

1

El tabcontrol tiene un miembro que no sea pública "lastSelection" que tiene la información que desee. Desafortunadamente, no veo una manera de llegar a eso. Es muy frustrante cuando tienen lo que quieres, pero no dejes que lo uses.

1

probar este en Deselect_Event:

private void tabControl1_Deselected(object sender, TabControlEventArgs e) 
{ 
    var test = e.TabPage.Text; 
} 
Cuestiones relacionadas