简体   繁体   English

如何在WinForms选项卡控件中指出要从哪个选项卡移动到哪个选项卡?

[英]How do I tell which tab you are moving from/to in a WinForms tab control?

I need to determine which tab the user is coming from, and going to, when they switch tabs, and possibly cancel the switch. 我需要确定用户来自哪个选项卡,以及切换选项卡时可能取消切换的选项卡。 I have tried the Deselecting, Deselected, Selecting, Selected events, and all of them show the e.TabPageIndex to be the same as the sender.SelectedIndex. 我尝试了取消选择,取消选择,选择,选定事件,并且所有这些事件都显示e.TabPageIndex与sender.SelectedIndex相同。

Is there an event, or property, that I can use so that I can determine both sides of this, or do I have to hack something together with caching it from one event and using that value in the new event. 是否存在可以使用的事件或属性,以便我可以确定其中的两个方面,或者我是否必须通过从一个事件缓存它并在新事件中使用该值来破解某些内容。

I am trying to avoid handling the Deselecting/Deselected events and caching the value to use in the Selecting event. 我试图避免处理取消选择/取消选择的事件并缓存要在选择事件中使用的值。 I already know I can do this, so I am asking if there is a cleaner way, without doing this. 我已经知道我可以做到这一点,所以我问是否有一种更清洁的方式,而不是这样做。

I have tried in both C# and VB, with the same results (no surprise). 我曾在C#和VB中尝试过,结果相同(毫不奇怪)。

Thanks. 谢谢。

It doesn't look like any one event argument will carry the details of both the previous and current tabs, so you'll need to handle a couple of events to keep track. 它看起来不像任何一个事件参数将包含前一个和当前选项卡的详细信息,因此您需要处理几个事件以跟踪。

At a minimum, you'd need to use the Deselected event to store a reference to the previously-selected tab. 至少,您需要使用Deselected事件来存储对先前选择的选项卡的引用。 You can always query the TabControl for its current tab. 您始终可以在TabControl中查询其当前选项卡。 To stretch a little further, you can also handle the Selected event to track the current tab. 要进一步拉伸,您还可以处理Selected事件以跟踪当前选项卡。

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

I believe the e.Cancel flag in the selecting event should do this trick. 我相信选择事件中的e.Cancel标志应该这样做。 This sends the selected tab back to the original on cancel: 这会在取消时将所选标签发送回原始标签:

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

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

If you really need more complex beharvior, subclassing the tab control will work, Then override the onSelecting method. 如果您确实需要更复杂的行为,则可以使用制表符控件的子类,然后覆盖onSelecting方法。 This shouldn't be done lightly. 这不应该轻易做到。 If the control is changed in the future you will have broken code. 如果将来更改控件,您将破坏代码。 And you have to confirm that all the behavior of the tab control are met (ie constructors ...) 并且您必须确认是否满足选项卡控件的所有行为(即构造函数...)

EDIT: based on feedback. 编辑:根据反馈。 This will internally track the original tab before selection. 这将在选择之前在内部跟踪原始选项卡。

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

}

You can subscribe to TabControl.Deselecting . 您可以订阅TabControl.Deselecting When it fires, the tab index in the event args will be the old index. 当它触发时,事件args中的选项卡索引将是旧索引。

You can then subscribe to TabControl.Selected . 然后,您可以订阅TabControl.Selected When this event fires, the tab index will be the index of the newly selected tab. 触发此事件时,选项卡索引将是新选择的选项卡的索引。

You can get the index of the tab the user is moving away from with the Deselecting event and store it in a variable for later use: 您可以使用Deselecting事件获取用户正在远离的选项卡的索引,并将其存储在变量中以供以后使用:

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

You want put code to prevent the switch in the Selecting event. 您希望使用代码来阻止选择事件中的切换。 Here's an example in VB.NET that will prevent you from selecting tab 2 on a tab control: 这是VB.NET中的一个示例,它将阻止您在选项卡控件上选择选项卡2:

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

You could do something like that : 你可以这样做:

    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
    }

To provide an alternative to my initial answer.... here's a sample of an extended TabControl which modifies the event arguments to include some more details. 为我的初始答案提供替代....这是一个扩展TabControl的示例,它修改事件参数以包含更多细节。

Disclaimer This is slapped together, it'll need some adjustments for sure! 免责声明这是打耳光的,它肯定需要一些调整!

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

...and a sample Form using this 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

The tabControl has a non-public member "lastSelection" that has the info you want. tabControl有一个非公共成员“lastSelection”,它包含您想要的信息。 Unfortunately, I don't see a way to get to it. 不幸的是,我没有办法找到它。 It's very frustrating when they have what you want but don't let you use it. 当他们拥有你想要的但却不让你使用它时,这是非常令人沮丧的。

Try this in Deselect_Event: 在Deselect_Event中尝试这个:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM