5

When the user clicks a button in the application, a window opens up. I want the TextBox belonging to the first item in the ItemsControl to be focused, so that the user can start typing as soon as the Window is opened, without needing to manually select the TextBox.

How can this be done?

For simplicity, we can say that the Window looks approximately like this:

<Window>
    <Grid>
        <ItemsControl ItemsSource="{Binding MyItems}">
            <DataTemplate>
                <Grid>
                    <StackPanel>
                        <StackPanel>
                            <customControls:ValidationControl>
                                <TextBox Text="" />
                            </customControls:ValidationControl>
                        </StackPanel>
                    </StackPanel>
                </Grid>
            </DataTemplate>
        </ItemsControl>
    </Grid>
</Window>

UPDATE After looking at propsed answers as well and this link: Window Loaded and WPF The modified solution is as follows:

<Window>
    <Grid>
        <ItemsControl x:Name="myItemsControl" ItemsSource="{Binding MyItems}">
            <DataTemplate>
                <Grid>
                    <StackPanel>
                        <StackPanel>
                            <customControls:ValidationControl>
                                <TextBox Text="" />
                            </customControls:ValidationControl>
                        </StackPanel>
                    </StackPanel>
                </Grid>
            </DataTemplate>
        </ItemsControl>
    </Grid>
</Window>

In constructor:

this.Loaded += new RoutedEventHandler(ThisWindowLoaded);

Loaded Method:

private void ThisWindowLoaded(object sender, RoutedEventArgs e)
{
    var textbox = FindVisualChild<TextBox>(myItemsControl.ItemContainerGenerator.ContainerFromIndex(0));
    FocusManager.SetFocusedElement(myItemsControl, textbox);
}

Super-duper method:

public static T FindVisualChild<T>(DependencyObject depObj) where T : DependencyObject
{
    if (depObj != null)
    {
        for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
        {
            DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
            if (child != null && child is T)
            {
                return (T)child;
            }

            T childItem = FindVisualChild<T>(child);
            if (childItem != null)
                return childItem;
        }
    }
    return null;
}
Community
  • 1
  • 1
Godspark
  • 354
  • 2
  • 13

3 Answers3

9

FocusManager.SetFocusedElement() may be what you are finding.

Xaml

   <ItemsControl x:Name="ItemsControl">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <TextBox />
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl> 

In Loaded event, you focus on first textbox:

   var textbox = ItemsControl.ItemContainerGenerator.ContainerFromIndex(0).FindChildByType<TextBox>();
   FocusManager.SetFocusedElement(ItemsControl, textbox);

Following is the way I find first child:

  public static T FindVisualChild<T>(DependencyObject depObj) where T : DependencyObject
    {
        if (depObj != null)
        {
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
            {
                DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
                if (child != null
                    && child is T)
                {
                    return (T)child;
                }

                T childItem = FindVisualChild<T>(child);
                if (childItem != null)
                    return childItem;
            }
        }
        return null;
    }
HungDL
  • 493
  • 2
  • 11
0

In case anybody is interested in: In my situation the ItemsControl has several different DataTemplates for different kind of items. Some are editable, some not. That's why I can not tell what kind of editor is currently displayed in which item. So I was looking for a different solution: I noticed, when I press the tab key once (right after the dialog opens), the focus moves to the intended element in my ItemsControl. That's why I generate a tab in the loaded event as so:

this.Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, (Action)delegate
{
    this.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
});
Helmut
  • 1
-2

If is WPF you should do smt like below :

<Grid>
        <DataGridCell>
            <Grid>
                <TextBox x:Name="TextBox1" Text=" ">

                    </TextBox>
            </Grid>
        </DataGridCell>

</Grid>

And code-behind:

 TextBox1.Focus();
Dragos Stoica
  • 1,753
  • 1
  • 21
  • 42
  • 2
    if you use ItemsControl, you have to use DataTemplate and is more tricky to find the Texbox using his name, but you can check this link : http://stackoverflow.com/questions/16375375/how-do-i-access-a-control-inside-a-xaml-datatemplate – Dragos Stoica Mar 26 '15 at 09:25