0

I am trying to implement a little search module in a WPF application. The results of the search are bound to a ListView and I want to set the focus on the first item of this ListView as soon as it is populated with new results.

The solution of this question - Set Item Focus in ListView WPF - suggests calling ContainerFromIndex(int index) method to get the necessary ListViewItem. Trying this at the very end of my search procedure returns null. So, I deduce that although the source of the ListView has been populated, the view itself isn't updated at this moment.

The next thing I tried is handling a SourceUpdated event of my ListView. It doesn't fire. I added NotifyOnSourceUpdated=True to the binding as was pointed out in the answer of this question - sourceupdated event not firing - but the event still doesn't fire.

I'll just add that the binding itself works. So, what is the right way to set focus on the first item (or on any other item) of a ListView?

EDIT: I'll supply the relevant part of the XAML to make things more clear:

<ListView Name="foundRequestsListView"
      IsSynchronizedWithCurrentItem="True"
      utils:GridViewSort.AutoSort="True"
      ItemsSource="{Binding Path=FoundRequests, NotifyOnSourceUpdated=True}"
      SourceUpdated="foundRequestsListView_SourceUpdated" >
    <ListView.Resources>...</ListView.Resources>
    <ListView.View>
        <GridView>...</GridView>
    </ListView.View>
</ListView>

FoundRequests property is an ordinary List.

EDIT: Calling UpdateLayout() beforehand solves the problem.

Community
  • 1
  • 1
Limbo Exile
  • 1,321
  • 2
  • 21
  • 41
  • I am binding just a `List` to the control. I added the relevant XAML to the question. As for the `SelectedItem` property, I didn't use it. I was able to programatically select an item, but not to make it focused. – Limbo Exile Dec 15 '14 at 16:03
  • You should bind the `ListView` to an `ObservableCollection` to get notified when the collection changes. Otherwise, the `ListView` control will fetch the items only once. – dymanoid Dec 15 '14 at 16:15
  • Tried that. The `SourceUpdated` event still doesn't fire. And `ListView` fetches the items after every search, so that wasn't really a problem. – Limbo Exile Dec 16 '14 at 07:19

3 Answers3

2

The problem is solved by calling UpdateLayout() method before trying to get a ListViewItem.

Limbo Exile
  • 1,321
  • 2
  • 21
  • 41
0

One way that you can achieve your requirement is to use the selected item that you say you have to access the associated ListViewItem that you can focus. Try this:

ListViewItem item = YourListView.ItemContainerGenerator.
    ContainerFromItem(YourSelectedItem) as ListViewItem;

Once you have the associated ListViewItem, you can focus it simply, like this:

item.Focus();
Sheridan
  • 68,826
  • 24
  • 143
  • 183
  • I don't exactly have it. Consider this: `foundRequestsListView.SelectedItem = foundRequestsListView.Items[0];` - this works and selects the first row (without focus). `ListViewItem item = foundRequestsListView.Items[0] as ListViewItem;` - this doesn't work: item is `null`, so I cannot use it. – Limbo Exile Dec 16 '14 at 07:34
  • Look at my example again... I never suggested that you could cast your data item into a `ListViewItem`. You need to use the `ItemContainerGenerator` class to generate the `ListViewItem` from the selected item as I showed you. Just use `foundRequestsListView.Items[0]` as your selected item if you haven't stored it in a variable. – Sheridan Dec 16 '14 at 09:56
  • I hope I am not misunderstanding you again. Do you suggest this to get the item? `ListViewItem item = foundRequestsListView.ItemContainerGenerator.ContainerFromItem(foundRequestsListView.Items[0]) as ListViewItem;` Even this way item is still `null` despite the fact that the `ListView` isn't empty. – Limbo Exile Dec 16 '14 at 10:36
  • I did mean that, so it's strange that your item is `null`. Perhaps you could try using the `foundRequestsListView.SelectedItem` property instead? If that still doesn't work, then I suggest that you search online for *ItemContainerGenerator.ContainerFromIndex returns null*. – Sheridan Dec 16 '14 at 11:17
0

Bind the SelectedItem to a property in your ViewModel.

SelectedItem="{Binding PropertyNameHere}"

When the selected item is changed on the collection, it will also be updated on the property bound to the selected item.

So at the end of your search procedure, simply set the bound property to the first item in the collection.

if (FoundRequests.Count > 0)
   PropertyNameHere = FoundRequests[0];

You do not need to worry about INotifyPropertyChanged for the bound property.

Mike Eason
  • 9,525
  • 2
  • 38
  • 63