8

Using TabControl.SelectTab("...") shows the tab but it also gives the tab focus. I would like to show a particular tab, but keep focus where it is.

I have data rows in a grid. Based on properties of the selected row, I show a different tab page to have a different UI layout. But when using arrow keys to scroll through rows, the focus switches to the selected tab -- which I don't want to happen.

Thanks.

TheSean
  • 4,516
  • 7
  • 40
  • 50

4 Answers4

16

You can try disabling the TabControl before setting the selected tab, then re-enabling it. This will prevent it from taking focus. I tested this on a tab control with a few controls on it, and didn't see any visual change, but you'll have to try it in your UI and see whether it's ok for you.

tabControl1.Enabled = false;
tabControl1.SelectTab("tabPage4");
tabControl1.Enabled = true;

To be safe, you could put the line to re-enable the TabControl in a finally block to make sure it doesn't get left disabled.

Jeff Ogata
  • 56,645
  • 19
  • 114
  • 127
  • This is nice idea and it works correctly, but the performance is not very good to enable/disable the control. The reason is that each of my tab pages has a lot of controls, so each one is disabled/enabled, which takes a lot of time and does not look great in UI. – TheSean Oct 29 '10 at 17:48
  • @TheSean, I don't know if there is another way to stop it from taking focus. I take it that taking the focus back from the tab control after the user selects a new row in the grid does not work for you? – Jeff Ogata Oct 29 '10 at 19:14
  • I previously deleted my solution, because is a bit hacky/workaroundish but maybe faster than disable/enable the tabcontrol. I undeleted it if you wanna try ;) – digEmAll Oct 30 '10 at 10:27
  • it does work, but its slow because of the large number of controls in my TabControl. – TheSean Nov 02 '10 at 12:21
  • Disabling the tab control has various side effects for the contained controls. So, watch out if you are calling this method as a reaction to an event from one of the contained controls. – tm1 May 15 '14 at 07:07
  • It is better to disable a single Tab Page rather than the entire control as supposed by Josh. – Elmue May 29 '18 at 19:16
4

I don't think there's a built-in function, but you can do in this way:

private bool skipSelectionChanged = false;

private void dataGridView_SelectionChanged(object sender, EventArgs e)
{
    if (skipSelectionChanged)
        return;

    // supposing we decide tab[0] has to be selected...
    this.SelectTabWithoutFocus(this.tabControl1.TabPages[0]);
}

private void SelectTabWithoutFocus(TabPage tabPage)
{
    this.skipSelectionChanged = true;

    // "this" is the form in my case, so you get the current focused control
    // (ActiveControl), backup it, and re-set it after Tab activation

    var prevFocusedControl = this.ActiveControl;
    if (this.ActiveControl != null)
    {
        this.tabControl1.SelectedTab = tabPage;
        prevFocusedControl.Focus();
    }
    this.skipSelectionChanged = false;
}

Here, I backup the current focused control, select the desired tab, and finally set the focus to the original control.

Skipping boolean is necessary, because giving the focus to the grid you trigger SelectionChanged event again, causing infinite looping.

digEmAll
  • 56,430
  • 9
  • 115
  • 140
  • Although I don't think this is an ideal solution, this idea ended up working best in my application. Thanks. – TheSean Mar 10 '11 at 13:25
  • I'm not sure whether this solution will work in all cases, see [this question](http://stackoverflow.com/q/435433/806690). – tm1 May 15 '14 at 07:10
  • I tried this and did not like it because you see the Form flashing to forground and then to background. It is an ugly workaround. The solution from Josh works seamlessly. – Elmue May 29 '18 at 19:18
1

This selects the tab pages while keeping the focus on top, as asked here above:

            tc.TabPages[0].Enabled = false;
            tc.SelectTab(0);
            tc.TabPages[0].Enabled = true;

tc is here my instance for the TabControl type (i. e. it IS my tab control, and it has a few "tab pages"). This works properly for me. My purpose is to loop through these tab pages with the Left and Right keys (arrows) i. e. when I go forwards (by Key.Right) and reach the last tabpage I want to have my focus on [0] without activating the DataGridView which I have in that page, and when I go backwards (by Key.Left) and reach [0] I want to have [tc.TabCount - 1] enabled, which is the last one. The code for this case is:

            tc.TabPages[tc.TabCount - 1].Enabled = false;
            tc.SelectTab(tc.TabCount - 1);
            tc.TabPages[tc.TabCount - 1].Enabled = true;

The complete piece of code is:

    private bool KeyTc(System.Windows.Forms.Keys keyData)
    {
        if (keyData == K.Left && tc.SelectedIndex == 0)
        {
            tc.TabPages[tc.TabCount - 1].Enabled = false;
            tc.SelectTab(tc.TabCount - 1);
            tc.TabPages[tc.TabCount - 1].Enabled = true;
            return true;
        }
        else if (keyData == K.Right && tc.SelectedIndex == tc.TabCount - 1)
        {
            tc.TabPages[0].Enabled = false;
            tc.SelectTab(0);
            tc.TabPages[0].Enabled = true;
            return true;
        }
        return false;
    }

This bool KeyTc is returned to a case in a switch statement for key evaluation in:

protected override bool ProcessCmdKey(ref Message keyMsg, Keys keyData)
    { switch keyData { ... } }
Darshan Lila
  • 5,772
  • 2
  • 24
  • 34
Josh
  • 79
  • 3
  • Isn't this in essence the same answer as @adrift ? – MicroVirus Aug 30 '14 at 13:49
  • It is better to disable a single TabPage rather than the entire control or manually changing the focus of the Forms because you don't see anything flashing around. This answer whould be the accepted answer. I tried all answers and this one works best. – Elmue May 29 '18 at 19:20
0

Base on the solution proposed by "Jeff Ogata : You can try disabling the TabControl before setting the selected tab, then re-enabling it. This will prevent it from taking focus", here bellow my solution:

tabMain.SelectedPageChanging += (s, e) =>
        { 
            tabMain.Enabled = false;
        };

        tabMain.SelectedPageChanged += (s, e) =>
        {
            tabMain.Enabled = true;                
        };

Note: this code is using DevExpress "DevExpress.XtraTab.XtraTabControl".

  • It is better to disable a single Tab Page rather than the entire control as supposed by Josh. – Elmue May 29 '18 at 19:16