简体   繁体   中英

TabPage selection, move the Focus to the previous ActiveControl when a TabPage is reselected

I need some help to focus a particular control when a TabPage is revisited. I followed many other blogs, but I wasn't able to solve the problem myself.

I created the TabPages inside a MDIForm:

Public Sub Tab_Open(Of T As {Form, New})(name As String, NameofTab As String, Tabnumber As String)

    Dim _formByName As New Dictionary(Of String, Form)
    Dim Frm As Form = Nothing

    If Not _formByName.TryGetValue(name, Frm) OrElse _formByName(name).IsDisposed Then
        Frm = New T()
        _formByName(name) = Frm
    End If

    Dim childTab As TabPage = New TabPage With {
        .Name = NameofTab & " : " & Tabnumber,
        .Text = NameofTab & " : " & Tabnumber,
        .Tag = Frm.Name
    }

    Form1.tabForms.TabPages.Add(childTab)

    Frm.TopLevel = False
    Frm.FormBorderStyle = FormBorderStyle.None
    Frm.Parent = Form1.tabForms.TabPages(Form1.tabForms.TabCount - 1)
    Frm.Dock = DockStyle.Fill
    Frm.Show()
   
    Form1.tabForms.SelectedTab = childTab
    Form1.tabForms.Visible = True
End Sub

Let's assume that in first TabPage the Focus was on a TextBox (with TabIndex = 4 ), now I may be click on the second TabPage.
After some calculations, when I select the previous TabPage, the Focus should be set to the TextBox with TabIndex = 4 again, but that's not happening.

I tried to create a Dictionary in the MDIForm as:

Public Tab_Last_Focus_info As New Dictionary(Of String, String())

and in SelectedIndexChanged I have this code:

 Private Sub tabForms_SelectedIndexChanged(sender As Object, e As EventArgs) Handles tabForms.SelectedIndexChanged

    If Tab_Last_Focus_info.ContainsKey(tabForms.SelectedTab.Name) Then
        Dim FullTypeName1 As String = String.Format("{0}", Tab_Last_Focus_info.Item(tabForms.SelectedTab.Name))
        Dim Indxval As String = String.Format("{1}", Tab_Last_Focus_info.Item(tabForms.SelectedTab.Name))

        Dim FullTypeName As String = Application.ProductName & "." & FullTypeName1
        Dim FormInstanceType As Type = Type.GetType(FullTypeName, True, True)
        Dim frm As Form = CType(Activator.CreateInstance(FormInstanceType), Form)
        Dim Focus_on As Integer = Integer.Parse(Indxval)

        frm.Controls(Focus_on).Focus()
        ' Not working too =>
        ' frm.Controls(Focus_on).Select() 

        ' Invisible or disabled control cannot be activated =>
        ' ActiveControl = frm.Controls(Focus_on) 'System.ArgumentException: 
    End If
End Sub

In the Form, which is opened via a Menu, I have this code for the Control that's focused:

Private Sub All_Got_Focus(sender As Object, e As EventArgs) Handles TB_ImageLoc.GotFocus, TB_CompWebsite.GotFocus,
    TB_CompPinCD.GotFocus, TB_CompPAN.GotFocus, TB_CompName.GotFocus, TB_CompMobile.GotFocus,
    TB_CompMD.GotFocus, TB_CompLL.GotFocus, TB_CompGSTIN.GotFocus, TB_CompFax.GotFocus, TB_CompEmail.GotFocus,
    TB_CompCD.GotFocus, TB_CompAreaCity.GotFocus, RTB_CompADD.GotFocus, PB_Logo.GotFocus, DTP_CompEst.GotFocus, DGV_CompList.GotFocus,
    CHKB_CompIsRegTrans.GotFocus, CB_CompStateID.GotFocus, CB_CompDistrictID.GotFocus, But_Upd.GotFocus, But_SelectLogo.GotFocus,
    But_Search.GotFocus, But_Reset.GotFocus, But_Refresh.GotFocus, But_GridSelect.GotFocus, But_Exit.GotFocus, But_Edit.GotFocus,
    But_Del.GotFocus, But_Add.GotFocus
   
    If Form1.Tab_Last_Focus_info.ContainsKey(Form1.tabForms.SelectedTab.Name) Then
        Form1.Tab_Last_Focus_info.Remove(Form1.tabForms.SelectedTab.Name)
    End If

    Form1.Tab_Last_Focus_info.Add(Form1.tabForms.SelectedTab.Name, New String() {Me.Name, Me.ActiveControl.TabIndex})
End Sub

Now in TabIndexChange I'm getting a correct value from the Dictionary, but I'm not able to focus on the required tab.

Kindly help and let me know what I am missing or what need to taken care for this issue or please let me know any other better idea for the same.

First thing, a suggestion: test this code in a clean Project, where you have a MDIParent and one Form with a TabControl with 2 o more TabPages, containing different types of Controls. Test the functionality, then apply to the Project that is meant to use it.


You need to keep track of the selected Control in a TabPage - the current ActiveControl - switch to other TabPages, restore the previous ActiveControl in a TabPage when it's brought to front again.

The procedure is simple, implemented as follows:

  • To keep track of the current ActiveControl - the Control that has the Focus, you need to know when a Control becomes the ActiveControl. This Control of course must be child of a TabPage.
    The ContainerControl class (the class from which Form derives) has a protected virtual method, UpdateDefaultButton() , that's overridden in the Form class. It's used to determine which child Button is activated when a User presses the Enter Key.
    This method is called each time a new Control becomes the ActiveControl : overriding it, we can be informed when this happens, so we can check whether the new ActiveControl is one we're interested in, because it's child of a TabPage of our TabControl.

  • When the new ActiveControl is one we need to keep track of, we can store the reference of this Control and the Index of the TabPage it belongs to in a collection, so we can then use this reference, when the selected TabBage changes, to set it again as the ActiveControl in its TabPage.

Here, to store the state, I'm using a Dictionary(Of Integer, Control) , where the Key is the Index of the TabPage and the Value is the reference of its ActiveControl.

When the TabControl.Selected event is raised - after a TabPage has been selected - we can lookup the Dictionary and restore the previous ActiveControl of that TabPage if one was stored.

► Here, BeginInvoke() is used to defer the action of setting the new ActiveControl, because this also causes a call to UpdateDefaultButton() and this method is called before the TabControl.Selected event handler completes.

Public Class SomeMdiChildForm

    Private tabPagesActiveControl As New Dictionary(Of Integer, Control)()

    ' This method is called each time a Control becomes the ActiveControl
    Protected Overrides Sub UpdateDefaultButton()
        MyBase.UpdateDefaultButton()

        If TypeOf ActiveControl.Parent Is TabPage Then
            Dim tabPageIdx = CType(CType(ActiveControl.Parent, TabPage).Parent, TabControl).SelectedIndex
            If tabPagesActiveControl.Count > 0 AndAlso tabPagesActiveControl.ContainsKey(tabPageIdx) Then
                tabPagesActiveControl(tabPageIdx) = ActiveControl
            Else
                tabPagesActiveControl.Add(tabPageIdx, ActiveControl)
            End If
        End If
    End Sub

    Private Sub TabControl1_Selected(sender As Object, e As TabControlEventArgs) Handles TabControl1.Selected
        Dim ctrl As Control = Nothing
        If tabPagesActiveControl.TryGetValue(e.TabPageIndex, ctrl) Then
            BeginInvoke(New Action(Sub() Me.ActiveControl = ctrl))
        End If
    End Sub
End Class

C# Version :
(assume tabControl1 is the name of the TabControl instance)

public partial class SomeForm : Form
{
    private Dictionary<int, Control> tabPagesActiveControl = new Dictionary<int, Control>();

    // [...]

    // This method is called each time a Control becomes the ActiveControl
    protected override void UpdateDefaultButton()
    {
        base.UpdateDefaultButton();
        if (ActiveControl.Parent is TabPage tp) {
            var tabPageIdx = (tp.Parent as TabControl).SelectedIndex;
            if (tabPagesActiveControl.Count > 0 && tabPagesActiveControl.ContainsKey(tabPageIdx)) {
                tabPagesActiveControl[tabPageIdx] = ActiveControl;
            }
            else {
                tabPagesActiveControl.Add(tabPageIdx, ActiveControl);
            }
        }
    }

    private void tabControl1_Selected(object sender, TabControlEventArgs e)
    {
        if (tabPagesActiveControl.TryGetValue(e.TabPageIndex, out Control ctrl)) {
            BeginInvoke(new Action(() => ActiveControl = ctrl));
        }
    }
}

As mentioned previously Tab_Open sub is used to create a form as tab.

In Main form (MDI) created Dictionary as Public tabPagesActiveControl As New Dictionary(Of String, Integer)

In each form when the control is focused the value has been added to dictionary as

Private Sub DateTimePicker1_Leave(sender As Object, e As EventArgs) Handles RadioButton1.GotFocus,
        DateTimePicker1.GotFocus, ComboBox1.GotFocus, CheckBox1.GotFocus, Button1.GotFocus, TextBox3.GotFocus, TextBox4.GotFocus, RichTextBox1.GotFocus

        If Form1.tabPagesActiveControl.ContainsKey(Form1.TabControl1.SelectedTab.Name) Then
            Form1.tabPagesActiveControl(Form1.TabControl1.SelectedTab.Name) = Me.ActiveControl.TabIndex
        Else
            Form1.tabPagesActiveControl.Add(Form1.TabControl1.SelectedTab.Name, Me.ActiveControl.TabIndex)
        End If
        
    End Sub

And when the tab is focused:

Private Sub TabControl1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles TabControl1.SelectedIndexChanged

        If tabPagesActiveControl.ContainsKey(Me.TabControl1.SelectedTab.Name) Then
Dim Indxval As String = String.Format(tabPagesActiveControl.Item(Me.TabControl1.SelectedTab.Name))

            SendKeys.Send("{TAB " & Indxval & "}")

        End If

    End Sub

As mentioned in the comments it has flaws. Kindly please check and help or do let me know what can be tried.

Finally I solved the issue after struggling for 8 Days:)

As I mentioned earlier I Open the forms as tabs using the Sub Tab_Open mentioned in the question.

Defined or created a new dictionary in MDI form as

Public tabPagesActiveControl As New Dictionary(Of String, Control)

and defined a control variable as

Dim Sel_Control As Control

Now in each form when the control is focused I have the below code to assign the current control alone to the dictionary:

Private Sub All_Focus(sender As Object, e As EventArgs) Handles TBox_Reg_website.GotFocus,
        TBox_Reg_To.GotFocus, TBox_Reg_State.GotFocus, TBox_Reg_PinCD.GotFocus, TBox_Reg_PAN.GotFocus, TBox_Reg_office_num.GotFocus,
        TBox_Reg_mobile_num.GotFocus, TBox_Reg_GSTIN.GotFocus, TBox_Reg_fax_no.GotFocus, TBox_Reg_email.GotFocus, TBox_Reg_country.GotFocus,
        TBox_Reg_Company.GotFocus, TBox_Reg_City.GotFocus, TBox_Reg_Add2.GotFocus, TBox_Reg_Add1.GotFocus, TB_Curr_website.GotFocus,
        TB_Curr_state.GotFocus, TB_Curr_RegTo.GotFocus, TB_Curr_Pincd.GotFocus, TB_Curr_Pan.GotFocus, TB_Curr_office_num.GotFocus,
        TB_Curr_Mobile_num.GotFocus, TB_Curr_Gstin.GotFocus, TB_Curr_fax_no.GotFocus, TB_Curr_email.GotFocus, TB_Curr_country.GotFocus,
        TB_Curr_Company.GotFocus, TB_Curr_city.GotFocus, TB_Curr_add2.GotFocus, TB_Curr_add1.GotFocus,
        PICBox_Reg_Logo.GotFocus, MSP_Reg.GotFocus, Label9.GotFocus, Label8.GotFocus, Label7.GotFocus, Label6.GotFocus, Label5.GotFocus,
        Label4.GotFocus, Label3.GotFocus, Label2.GotFocus, Label15.GotFocus, Label14.GotFocus, Label13.GotFocus, Label12.GotFocus,
        Label11.GotFocus, Label10.GotFocus, Label1.GotFocus,
        ChkBx_Upd_Logo.GotFocus, Chkbox_NoLogo.GotFocus

        If Form1.tabPagesActiveControl.ContainsKey(Form1.TabControl1.SelectedTab.Name) Then
            Form1.tabPagesActiveControl.Remove(Form1.TabControl1.SelectedTab.Name)
        End If

        Form1.tabPagesActiveControl.Add(Form1.TabControl1.SelectedTab.Name, Me.ActiveControl)

    End Sub

and in the MDI form when tab select index changes having the below code:

Private Sub TabControl1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles TabControl1.SelectedIndexChanged

        If tabPagesActiveControl.ContainsKey(Me.TabControl1.SelectedTab.Name) Then
            
            Sel_Control = tabPagesActiveControl.Item(Me.TabControl1.SelectedTab.Name)
            
            Sel_Control.Focus()
            
        End If

    End Sub

Thanks:)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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