Search code examples
wpflistviewinternals

How can I access the ListViewItems of a WPF ListView?


Within an event, I'd like to put the focus on a specific TextBox within the ListViewItem's template. The XAML looks like this:

<ListView x:Name="myList" ItemsSource="{Binding SomeList}">
    <ListView.View>
        <GridView>
            <GridViewColumn>
                <GridViewColumn.CellTemplate>
                    <DataTemplate>
                        <!-- Focus this! -->
                        <TextBox x:Name="myBox"/>

I've tried the following in the code behind:

(myList.FindName("myBox") as TextBox).Focus();

but I seem to have misunderstood the FindName() docs, because it returns null.

Also the ListView.Items doesn't help, because that (of course) contains my bound business objects and no ListViewItems.

Neither does myList.ItemContainerGenerator.ContainerFromItem(item), which also returns null.


Solution

  • To understand why ContainerFromItem didn't work for me, here some background. The event handler where I needed this functionality looks like this:

    var item = new SomeListItem();
    SomeList.Add(item);
    ListViewItem = SomeList.ItemContainerGenerator.ContainerFromItem(item); // returns null
    

    After the Add() the ItemContainerGenerator doesn't immediately create the container, because the CollectionChanged event could be handled on a non-UI-thread. Instead it starts an asynchronous call and waits for the UI thread to callback and execute the actual ListViewItem control generation.

    To be notified when this happens, the ItemContainerGenerator exposes a StatusChanged event which is fired after all Containers are generated.

    Now I have to listen to this event and decide whether the control currently want's to set focus or not.