7
votes

I have different tabItems in a TabControl and each tabItem has some input fields.

I am moving between the tabItems programmatically (like a wizard to move from the first to the next)

I am using this code inside the "Next" button

tabItem2.isSelected = true;

my problem that when I move between the tabItems by clicking on them, the focus (keyboard focus) will move to the first textbox input.

But programmatically with the previous code, the focus won't move to the first input textbox item inside the tabItem.

Any idea?

2
Just out of interest, have you considered using the Frame control and Pages, rather than a TabControl? It's much better suited for wizard-style UIs.Matt Hamilton
the answer I gave was wrong! :(Pratik Deoghare

2 Answers

3
votes

If you're forcing the IsSelected property, I'd also give the first TextBox a name and set the focus after you set the selected tab.

If you're building your UI dynamically, this won't work, but you can create a utility method which searches the logical tree (or the visual tree if you're using presenters/view-models) for the first input control and then set the focus.

0
votes

These solutions didn't work for me. It got as far selecting the TabItem I wanted, but it wasn't able to select/focus the desired TreeViewItem. (It would only focus the TVI if the TabItem was already selected.) The solution below finally worked for me.

(FYI: The snippets below are part of app that is similar to Microsoft Help Viewer 2.0. When you click the "Sync" button, it first selects the Contents tab if not already selected, then traverses into tree view until it finds the matching tree view item. Which it then selects/focuses.)

Cheers

private void OnClick_SyncContents(object sender, RoutedEventArgs e)
{
    // If the help-contents control isn't visible (ie., some other tab is currently selected),
    // then use our common extension method to make it visible within the tab control.  Once
    // it visible, the extension method will call the event handler passed (which is this method)
    if (!this.m_UcHelpFileContents.IsVisible)
    {
      this.m_UcHelpFileContents.
      SelectParentTabItem_WaitForMeToBecomeVisible_ThenCallThisEventHandlerWithNullArguments
      (this.OnClick_SyncContents);
    }
    else 
    {
      // Else the help-contents control is currently visible, thus focus the 
      // matching tree view item
      /* Your code here that focuses the desired tree view item */
    }
}


public static class CommonExtensionMethods
{
  public static void
    SelectParentTabItem_WaitForMeToBecomeVisible_ThenCallThisEventHandlerWithNullArguments
    (this FrameworkElement frameworkElement, RoutedEventHandler eventHandlerToCallWhenVisible)
  {
    // First, define the handler code for when the given framework element becomes visible
    DependencyPropertyChangedEventHandler HANDLER = null;
    HANDLER = (s, e) =>
    {
      // If here, the given framework element is now visible and its tab item currently selected
      // Critical: first and foremost, undo the latch to is-visible changed
      frameworkElement.IsVisibleChanged -= HANDLER;

      // Now invoke the event handler that the caller wanted to invoke once visible
      frameworkElement.Dispatcher.BeginInvoke(eventHandlerToCallWhenVisible, null, null);
    };

    // Use our common extension method to find the framework element's parent tab item
    TabItem parentTabItem = frameworkElement.GetFirstParentOfType<TabItem>();

    if (parentTabItem != null)
    {
      // Assign the handler to the given framework element's is-visible-changed event
      frameworkElement.IsVisibleChanged += HANDLER;

      // Now set the tab item's is-selected property to true (which invokes the above 
      // handler once visible)
      parentTabItem.IsSelected = true;
    }
  }


  public static T GetFirstParentOfType<T>
    (this FrameworkElement frameworkElement) where T : FrameworkElement
  {
    for (FrameworkElement fe = frameworkElement.Parent as FrameworkElement; 
         fe != null; 
         fe = fe.Parent as FrameworkElement)
    {
      if (fe is T)
        return fe as T;
    }

    // If here, no match
    return null;
  }
}