Set focus to 1st textbox in items control
Asked Answered
C

1

6

Let's say I have an items control that is bound to a list of items on the VM. Inside the datatemplate is a textbox. How would I set focus to the first textbox in either XAML or the VM?

Thanks in advance for any help!

<ItemsControl ItemsSource="{Binding UsageItems}" Grid.Row="1" Focusable="False">
<ItemsControl.ItemTemplate>
    <DataTemplate>
            <Grid Margin="0,0,0,3">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="100"/>
                <ColumnDefinition Width="10"/>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="10"/>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="10"/>
                <ColumnDefinition Width="Auto"/>
            </Grid.ColumnDefinitions>

            <TextBlock Text="{Binding Month}" Style="{StaticResource Local_MonthLabel}" />
            <core:NumericTextBox Value="{Binding Actual, Mode=OneWay}" Style="{StaticResource Local_ActualUsageEntry}" Grid.Column="2"/>

            <core:ValidationControl Instance="{Binding Model}" Grid.Column="4" PropertyName="{Binding MonthNumber, StringFormat=AdjustedUsage{0}}">
                <core:NumericTextBox Value="{Binding Adjusted}"  DefaultValueIfNull="0" Style="{StaticResource Local_AdjustUsageEntry}" x:Name="AdjustmentEntry" inventoryLocationSetup:InitialFocusBehavior.Focus="True" />
            </core:ValidationControl>

            <telerik:RadComboBox ItemsSource="{Binding Converter={StaticResource Converter_EnumToEnumMemberViewModel}, Mode=OneTime, Source={x:Type Enums:UsageAdjustmentTypes}}" SelectedValue="{Binding Code, Mode=TwoWay}" Grid.Column="6" Style="{StaticResource Local_CodeSelector}"/>

        </Grid>
    </DataTemplate>
</ItemsControl.ItemTemplate>

Concordant answered 1/5, 2013 at 21:51 Comment(0)
A
5

I use an attached behaviour:

public static class InitialFocusBehavior
{
    public static bool GetFocus(DependencyObject element)
    {
        return (bool)element.GetValue(FocusProperty);
    }

    public static void SetFocus(DependencyObject element, bool value)
    {
        element.SetValue(FocusProperty, value);
    }

    public static readonly DependencyProperty FocusProperty =
        DependencyProperty.RegisterAttached(
        "Focus",
        typeof(bool),
        typeof(InitialFocusBehavior),
        new UIPropertyMetadata(false, OnElementFocused));

    static void OnElementFocused(
        DependencyObject depObj, DependencyPropertyChangedEventArgs e)
    {
        FrameworkElement element = depObj as FrameworkElement;
        if (element == null)
            return;
        element.Focus();
    }
}

Then in the XAML bind it to True for the element you want focused:

<TextBox Width="200" Height="20" local:InitialFocusBehavior.Focus="True" />

=== UPDATE ===

Sorry, the code above just shows how to use a behaviour to give focus to a control on the page, if you want to do it to an element in the first item in an ItemControl then you'll have to instead apply the behavior to the ItemsControl itself and then in your update handler find the child by doing something like this instead:

static void OnElementFocused(DependencyObject depObj, DependencyPropertyChangedEventArgs e)
{
    ItemsControl itemsControl = depObj as ItemsControl;
    if (itemsControl == null)
        return;
    itemsControl.Loaded += (object sender, RoutedEventArgs args) =>
    {
        // get the content presented for the first listbox element
        var contentPresenter = (ContentPresenter)itemsControl.ItemContainerGenerator.ContainerFromIndex(0);

        // get the textbox and give it focus
        var textbox = contentPresenter.ContentTemplate.FindName("myTextBox", contentPresenter) as TextBox;
        textbox.Focus();
    };
}

You'll notice that I'm setting the focus inside the OnLoaded handler because I'm assuming that the items won't have been attached yet when the control is first created.

Also you've probably already figured it out by "local" is just the namespace that the InitialFocusBehavior class is defined in, you'll need to add something like this at the top of the xaml:

xmlns:local="clr-namespace:YourProjectNamespace"
Abernathy answered 1/5, 2013 at 23:44 Comment(4)
Thanks Mark, I am trying to test this out but it doesn't like the XAML, all red. Where does "local:" come from? Sorry, not a XAML developer. :-)Concordant
Ok well I tried it and it does not work. The focus isn't even in a control in the ItemsControl DataTemplate, it is in a textbox outside of the control. It did pop into the OnElementFocused, but it went to that method one time for each control that got created (1 for each item in the list of items it is bound to) which leads me to believe that even if this did work it would set the focus to the last textbox, not the first. Any other ideas? I will post my xaml below.Concordant
Is there any way we can focus the first textbox within an Itemscontrol (having itemtemplate)? i tried the above approach, but not working!Manicurist
your updated solution worked for me. i also wanted to focus on first textbox in itemscontrol and it worked like a charm.Stabler

© 2022 - 2024 — McMap. All rights reserved.