Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to focus a datatemplated TextBox in the first element of an ItemsControl in a Window, when the Window is opened? (C#, WPF)

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;
}
like image 200
Godspark Avatar asked Mar 26 '15 08:03

Godspark


1 Answers

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;
    }
like image 120
HungDL Avatar answered Oct 23 '22 09:10

HungDL