0

I have a TabControl that contains a TextBox per tab. I need to select a tab programmatically and then set the selection of the TextBox and set the focus to the TextBox.

My problem is, when I first select a new tab in code and then set the focus to the textbox it doesn't work.

When the desired tab is already the selected tab and I set the focus to the textbox inside the tab, it's working.

It seems, that performing several actions on WPF elements does not work.

What is the right way to first switch the tab of a tabcontrol and then set the focus to a child in the newly selected TabItem?


Edit: I've found something on the Internet: Waiting for the render thread to complete:

https://social.msdn.microsoft.com/Forums/vstudio/en-US/693fbedb-efa6-413e-ab66-530c6961d3fb/how-to-wait-for-the-wpf-render-thread-to-catch-up?forum=wpf

Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, new Action(() => { })).Wait();

But is this the right way?

BTW: What is the difference between:

Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, new Action(() => { })).Wait();
Dispatcher.Invoke(DispatcherPriority.ApplicationIdle, new Action(() => { }));
be_mi
  • 529
  • 6
  • 21
  • *"performing several actions on WPF elements does not work"* - it depends when and how you do it. Can you show us? – Sinatr Mar 20 '17 at 16:25
  • You may need to schedule the focus change to happen later on the Dispatcher. It might be that the actual visual tree change due to the tab change isn't synchronous, but just happens "whenever the dispatched thread is free again". So when you try to set focus right after the tab change the text box isn't even visible yet, let alone being able to receive focus due to that. – Joey Mar 20 '17 at 16:28
  • Seems you aren't [alone](http://stackoverflow.com/q/4553412/1997232) though. Still, having [mcve](https://stackoverflow.com/help/mcve) may attract someone to try to solve the problem. – Sinatr Mar 20 '17 at 16:28
  • @Joey: What do you exactly mean by schedule on the dispatcher? – be_mi Mar 20 '17 at 16:34
  • @be_mi: Dispatcher.BeginInvoke. – Joey Mar 20 '17 at 18:25
  • Try writing a Behavior for the TextBox, that handled its Loaded event, and then places the focus on it(Loaded will be called eacht time you switch Tab, but after UI done loading). – Mishka Mar 21 '17 at 05:50

1 Answers1

0

Use the FocusManager.SetFocusedElement() method.

Focus has some nuances, you can learn more here.

XAML

<TabControl>
    <TabItem Header="One"
             x:Name="tabOne">
        <Button HorizontalAlignment="Center"
                VerticalAlignment="Center"
                Content="Set Focus"
                Click="Button_Click" />
    </TabItem>
    <TabItem Header="Two"
             Name="tabTwo">

        <StackPanel>
            <TextBox Name="txtOne" />
            <TextBox Name="txtTwo" />
        </StackPanel>
    </TabItem>
    <TabItem Header="Three"
             x:Name="tabThree">
        <StackPanel>
            <TextBox Name="txtThree" />
            <TextBox Name="txtFour" />
        </StackPanel>
    </TabItem>
</TabControl>

CODE

private void Button_Click(object sender, RoutedEventArgs e)
{
  tabTwo.IsSelected = true;
  FocusManager.SetFocusedElement(tabTwo, txtTwo);

}
Walt Ritscher
  • 6,977
  • 1
  • 28
  • 35