none
How to stop tab control from automatically setting focus

    Question

  • Hi all,

    I have a tablet pc application with a custom virtual keypad.
    When a textbox gets focus, the keypad is shown.

    I would like to disable the Focus that is used by a TabControl. (Because this triggers unwanted showing of the keypad).

    How can I avoid the setting of focus by the TabControl? (Look at the very simple example on this thread which shows the out-of-the-box focusing from the 1st control inside a tabPanel when you switch between tabs: http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/6b7a8c04-0bba-41d2-8afd-ac4c7c0533c9)

    I would like to avoid writing load event handlers who set the focus to some none-textbox field.


    Any tips / hints / guidance?
    If you need additional info just let me know!!

    Kind regards,
    Wim
    Thursday, May 28, 2009 1:08 PM

Answers

  • Hi,
    I see now what you want. Interesting question!
    Take the notice: the thing you don't like happens only if you select a tab by the left mouse button. If from the application start you navigate with just tabs or/and arrow all goes right. So we can suppose that the TabItem propagates the focus to its children when clicked by left mouse button. So we should prevent it from doing so.

    <Window x:Class="WpfApplication1.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Name="theWindow" Title="Window1" 
       Height="300" Width="300"
       UIElement.GotFocus="OnGotFocus" UIElement.GotKeyboardFocus="OnGotKeyboardFocus"
       UIElement.PreviewMouseLeftButtonDown="OnPreviewMouseLeftButtonDown">
        <Grid>
          <Grid.RowDefinitions>
             <RowDefinition Height="Auto"/>
             <RowDefinition/>
          </Grid.RowDefinitions>
          
          <Button Name="FakeButton">Fake button</Button>
          <TabControl Grid.Row="1" SelectionChanged="TabControl_SelectionChanged">
             <TabItem Name="Tab1" Header="1st tab">
                <StackPanel Name="Tab1StackPanel">
                   <TextBox Name="Tab1TextBox1"/>
                   <TextBox Name="Tab1TextBox2"/>
                </StackPanel>
             </TabItem>
             <TabItem Name="Tab2" Header="2ndt tab">
                <StackPanel Name="Tab2StackPanel">
                   <TextBox Name="Tab2TextBox1"/>
                   <TextBox Name="Tab2TextBox2"/>
                </StackPanel>
             </TabItem>
          </TabControl>
       </Grid>
    </Window>
    

    public partial class Window1 : Window
    {
       public Window1()
       {
          InitializeComponent();
       }
    
       private void OnGotFocus(object sender, RoutedEventArgs e)
       {
           Trace.WriteLine(string.Format("***** {0} name={1} got logical focus"
             , e.OriginalSource.GetType().Name, (e.OriginalSource as FrameworkElement).Name));
       }
    
       private void OnGotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
       {
          Trace.WriteLine(string.Format("***** {0} name={1} got keyboard focus"
             , e.OriginalSource.GetType().Name, (e.OriginalSource as FrameworkElement).Name));
       }
    
       private void OnPreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
       {
          if (e.OriginalSource.GetType() == typeof(TabItem))
             e.Handled = true;
       }
    
       private void TabControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
       {
          ((e.OriginalSource as TabControl).SelectedItem as TabItem).Focus();
       }
    }
    
    Maybe it isn't the complete solution, but hope it'll help.

    Regards



    Oleg V. Polikarpotchkin
    • Edited by ov-p Friday, May 29, 2009 4:03 PM
    • Marked as answer by hypo Tuesday, June 02, 2009 7:35 AM
    Friday, May 29, 2009 3:17 PM

All replies

  • Hi,
    If I got your problem right setting TextBox IsTabStop property to False will solve it.
    Regards


    Oleg V. Polikarpotchkin
    Thursday, May 28, 2009 2:58 PM
  • But then I can't tab though my textboxes if I want!!!!

    I just don't want the tabcontrol to force an initial focus on a control. (And most of all I don't want to accomplish this by writing unnecessary code.) It is that action that happens but I don't want it to happen!!

    (You are right with the IsTabStop, but this throws the whole tabbing functionality overboard!!)


    Please help!

    Kind regards,
    Wim
    Thursday, May 28, 2009 3:09 PM
  • To get something happen (or not happen) in your code you should write something either in C#, VB or XAML - it's unavoidable. E.g. you can set IsTabStop="False" in XAML. If it isn't what you desire for some reason, be more specific!
    For example, is this TextBox the only control on the TabItem participating in tab navigation? If it isn't use TabIndex to control this navigation.
    Cheers
    Oleg V. Polikarpotchkin
    Thursday, May 28, 2009 5:23 PM
  • My objective is very easy:

    1. I don't want any control on a tabpanel to get focus unless I say so (by setting focus to it).
    2. I want to be able to tab through my controls inside a tabpanel when it is visible and when I start tabbing.

    In winforms:
    I create a tabcontrol, with 3 tabs, each tab contains a textbox.
    When I switch between the tabs, none of the controls in the tabpanels get focus. ==> For me this is logical/out-of-the-box behavior.

    In WPF:
    I create a tabcontrol, with 3 tabs, each tab contains a textbox.
    When I switch between the tabs, the textboxes inside the tabpanels get focus !!!!! ===> Not logical behavior, I didn't request these focuses, I don't want to write code to avoid these things because that's very weird code IMO.

     

    Can anyone tell me:
    Is that WPF behavior of the tabcontrol normal? If so, why?
    How to disable it in a proper way without setting IsTabStop (then I lose tabbing functionality, which I require).

     

    If my case is still not clear don't hesitate to question me ;)


    EDIT: Here is an example with on Tab3 the functionality that I want, But I DONT want to do it this way !!!! If someone else watches the code, or I watch the code after 3 months, then I'm going to wonder why I've put that button there you see!!! (the button is to catch the focus, so that I have no visible focus on any of my controls and still have tab functionality)

    <Window x:Class="WpfApplication1.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window1" Height="300" Width="300">
        <Grid>
            <TabControl>
                <TabItem Header="Cheese">
                    <StackPanel>
                        <Label></Label>
                        <TextBlock Focusable="True">The Cheese Tab</TextBlock>
                        <TextBox TabIndex="1"></TextBox>
                        <TextBox TabIndex="2"></TextBox>
                        <TextBox TabIndex="3"></TextBox>
                    </StackPanel>
                </TabItem>
                <TabItem Header="Pepperoni">
                    <StackPanel>
                        <Rectangle></Rectangle>
                        <TextBlock>Peperoni</TextBlock>
                        <TextBox TabIndex="1"></TextBox>
                        <TextBox TabIndex="2"></TextBox>
                        <TextBox TabIndex="3"></TextBox>
                    </StackPanel>
                </TabItem>
                <TabItem Header="Mushrooms">
                    <StackPanel>
                        <Button TabIndex="1" Width="0" Height="0" HorizontalAlignment="Left" VerticalAlignment="Top"></Button>
                        <TextBlock>Mushrooms</TextBlock>
                        <TextBox TabIndex="2"></TextBox>
                        <TextBox TabIndex="3"></TextBox>
                        <TextBox TabIndex="4"></TextBox>
                    </StackPanel>
                </TabItem>
            </TabControl>
        </Grid>
    </Window>


    Kind regards,
    Wim

    • Edited by hypo Friday, May 29, 2009 8:50 AM
    Friday, May 29, 2009 8:26 AM
  • Hi,
    I see now what you want. Interesting question!
    Take the notice: the thing you don't like happens only if you select a tab by the left mouse button. If from the application start you navigate with just tabs or/and arrow all goes right. So we can suppose that the TabItem propagates the focus to its children when clicked by left mouse button. So we should prevent it from doing so.

    <Window x:Class="WpfApplication1.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Name="theWindow" Title="Window1" 
       Height="300" Width="300"
       UIElement.GotFocus="OnGotFocus" UIElement.GotKeyboardFocus="OnGotKeyboardFocus"
       UIElement.PreviewMouseLeftButtonDown="OnPreviewMouseLeftButtonDown">
        <Grid>
          <Grid.RowDefinitions>
             <RowDefinition Height="Auto"/>
             <RowDefinition/>
          </Grid.RowDefinitions>
          
          <Button Name="FakeButton">Fake button</Button>
          <TabControl Grid.Row="1" SelectionChanged="TabControl_SelectionChanged">
             <TabItem Name="Tab1" Header="1st tab">
                <StackPanel Name="Tab1StackPanel">
                   <TextBox Name="Tab1TextBox1"/>
                   <TextBox Name="Tab1TextBox2"/>
                </StackPanel>
             </TabItem>
             <TabItem Name="Tab2" Header="2ndt tab">
                <StackPanel Name="Tab2StackPanel">
                   <TextBox Name="Tab2TextBox1"/>
                   <TextBox Name="Tab2TextBox2"/>
                </StackPanel>
             </TabItem>
          </TabControl>
       </Grid>
    </Window>
    

    public partial class Window1 : Window
    {
       public Window1()
       {
          InitializeComponent();
       }
    
       private void OnGotFocus(object sender, RoutedEventArgs e)
       {
           Trace.WriteLine(string.Format("***** {0} name={1} got logical focus"
             , e.OriginalSource.GetType().Name, (e.OriginalSource as FrameworkElement).Name));
       }
    
       private void OnGotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
       {
          Trace.WriteLine(string.Format("***** {0} name={1} got keyboard focus"
             , e.OriginalSource.GetType().Name, (e.OriginalSource as FrameworkElement).Name));
       }
    
       private void OnPreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
       {
          if (e.OriginalSource.GetType() == typeof(TabItem))
             e.Handled = true;
       }
    
       private void TabControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
       {
          ((e.OriginalSource as TabControl).SelectedItem as TabItem).Focus();
       }
    }
    
    Maybe it isn't the complete solution, but hope it'll help.

    Regards



    Oleg V. Polikarpotchkin
    • Edited by ov-p Friday, May 29, 2009 4:03 PM
    • Marked as answer by hypo Tuesday, June 02, 2009 7:35 AM
    Friday, May 29, 2009 3:17 PM
  • Tnx ov-p for a better insight of when the focus event occurs.

    I am going for the workaround solution :)

    Still I am disappointed in the fact that it happens in the first place!
    (It doesn't happen in winforms)


    Kind regards,
    Wim
    Tuesday, June 02, 2009 7:37 AM