OscarRyz
OscarRyz

Reputation: 199215

Give focus to a component inside an expander

I have this requirement where I need to focus the first element inside the expander when the user press tab.

Currently (default behavior) the focus goes to the expander, I've tried to focus the first element of the expander by creating a focus event handler in the expander like this:

private void ExpanderGotFocus(object sender, RoutedEventArgs e)
{
    var expander = (Expander) sender;

    if (!expander.IsExpanded)
    {
        expander.IsExpanded = true;
        this._someText.Focus();
    }        
}

Which doesn't work.

I've also tried to give the focus the the next element:

var tRequest = new TraversalRequest(FocusNavigationDirection.Next);
var keyboardFocus = Keyboard.FocusedElement as UIElement;
keyboardFocus.MoveFocus(tRequest);

But only works the second time ( when the expander has been at least opened once )

I've tried to put this in a thread and some other crazy ideas.

How can I give focus to the first element inside an expander? ( the first time the expander is closed )

Upvotes: 2

Views: 1569

Answers (2)

Ponmalar
Ponmalar

Reputation: 7031

Check with the following,

XAML code:

<StackPanel>
        <Expander Header="Expander"
                  Name="expander"
                  Collapsed="OnCollapsed"
                  IsExpanded="True" >
            <StackPanel>
                <TextBox Text="Text1" Name="textBox1" />
                <TextBox Text="Text2" Name="textBox2"  />
                <TextBox Text="Text3" Name="textBox3"  />
            </StackPanel>
        </Expander>
        <TextBox Text="Text4" Name="textBox4" />
</StackPanel>

in the code behind:
public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
            this.Loaded += delegate
            {
                textBox2.Focus();
            };
        }
        private void OnCollapsed(object sender, RoutedEventArgs e)
        {
            var element = Keyboard.FocusedElement;
            if (element != null)
            {
                //now is the ToggleButton inside the Expander get keyboard focus
                MessageBox.Show(element.GetType().ToString());
            }
            //move focus
            Keyboard.Focus(textBox4);
        }
}

Upvotes: 0

OscarRyz
OscarRyz

Reputation: 199215

I tried several ways and none of them worked, basically the problem is the TextBox is still rendering when the expander is expanding ( to early ).

So instead what I've found is to add the IsVisibleChanged event to the textbox so when the expander finished the textbox become visible and request the focus

XAML

<Expander GotFocus="ExpanderGotFocus">
    <Expander.Header>
        <TextBlock Text="{x:Static Client:Strings.XYZ}" />
    </Expander.Header>
    <Expander.Content>
        <StackPanel>
            <TextBox IsVisibleChanged="ControlIsVisibleChanged"  Name="txtBox" />
        </StackPanel>
    </Expander.Content>
</Expander>

Code behind

private void ExpanderGotFocus(object sender, RoutedEventArgs e)
{
    var expander = (Expander) sender;

    if (!expander.IsExpanded )
    {
        expander.IsExpanded = true;
    }
}

private void ControlIsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
    Keyboard.Focus((IInputElement)sender);
}

Upvotes: 6

Related Questions