1

I have a WPF ItemsControl that is bound to an ObservableCollection.

The XAML:

    <ItemsControl Name="mItemsControl">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <TextBox Text="{Binding Mode=OneWay}"></TextBox>    
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>

The codebehind:

    private ObservableCollection<string> mCollection = new ObservableCollection<string>();

    public MainWindow()
    {
        InitializeComponent();

        this.mCollection.Add("Test1");
        this.mCollection.Add("Test2");
        this.mItemsControl.ItemsSource = this.mCollection;
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        this.mCollection.Add("new item!");
    }

When I click a button, it adds a new string to the databound ObservableCollection which triggers a new TextBox to appear. I want to give this new textbox focus.

I've tried this technique from a related StackOverflow question but it always sets focus to the textbox before the newly created one.

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        this.mCollection.Add("new item!");

        // MoveFocus takes a TraversalRequest as its argument.
        TraversalRequest request = new TraversalRequest(FocusNavigationDirection.Previous);

        // Gets the element with keyboard focus.
        UIElement elementWithFocus = Keyboard.FocusedElement as UIElement;

        // Change keyboard focus.
        if (elementWithFocus != null)
        {
            elementWithFocus.MoveFocus(request);
        }
    }

My need seems simple enough, but it's almost like the new textbox doesn't really exist until a slight delay after something is added to the ObservableCollection.

Any ideas of what would work?

Thanks!

-Mike

Community
  • 1
  • 1
Mike
  • 5,560
  • 12
  • 41
  • 52
  • For what it's worth: "it's almost like the new textbox doesn't really exist until a slight delay after something is added to the ObservableCollection." You are exactly correct: the ListBoxItem is not created until WPF updates its bindings, and this happens asynchronously as a background task (see the DispatcherPriority enum for how it fits in with other WPF processing). Not that this helps you solve the problem, but just thought you might like to have your suspicions confirmed! – itowlson Mar 16 '10 at 02:43

1 Answers1

3

Bit of a hack but try using the Dispatcher and BeginInvoke:

this.Dispatcher.BeginInvoke(new Action( ()=>{
    // MoveFocus takes a TraversalRequest as its argument.
    TraversalRequest request = new TraversalRequest(FocusNavigationDirection.Previous);

    // Gets the element with keyboard focus.
    UIElement elementWithFocus = Keyboard.FocusedElement as UIElement;

    // Change keyboard focus.
    if (elementWithFocus != null)
    {
        elementWithFocus.MoveFocus(request);
    }


}), DispatcherPriority.ApplicationIdle);
BFree
  • 102,548
  • 21
  • 159
  • 201