paparazzo
paparazzo

Reputation: 45096

GridView loses SelectedIndex value when ItemsSource is refreshed

Microsoft I think this may be a bug. Have a ListView GridView to display a single record.

Naturally the down arrow key navigates through the ListViewItems. That is the behavior I expect. In XAML the ItemsSource and SelectedIndex is bound. The behavior I want is the right and left arrow keys to navigate to the next and prior record.

The way I achieved this is to handle ListView PreviewKeyDown Event. The problem I had is the SelectedIndex is reset to -1 when the ItemSource is refreshed and I want it to stay on the old SelectedIndex. So I had to manually reset the SelectedIndex as shown below.

Here is my problem: After AND ONLY DIRECTLY AFTER a left arrow or right arrow key the up and down keys do not pass the correct value for SelectedIndex.

For example SelectedIndex = 4 then right arrow and then down key the value passed to SelectedIndex is 0 and the value passed should be 4. The ListView is visually on SelectedIndex 4 so it is like it knows the SelectedIndex is 4 but it also does not know. If I do not change the ItemsSource the up and down arrow keys work correctly. I tried KeyDown and KeyUp events but in the case those events just don't fire at all in the fail condition described above.

WPF 4.0 Visual Studio 2010.

private void lvCurDocFields_PreviewKeyDown(object sender, KeyEventArgs e)
{
    Debug.WriteLine("lvCurDocFields_PreviewKeyDown " + e.Key.ToString());
    e.Handled = false;
    Int32 lastIndex;
    switch (e.Key)  // e.KeyCode
    {
        case Key.Right:
            lastIndex = lvCurDocFields.SelectedIndex;
            App.StaticGabeLib.Search.SelectedDocIndex++;
            if (lvCurDocFields.SelectedIndex != lastIndex)
            {
                lvCurDocFields.SelectedIndex = lastIndex;
            }
            e.Handled = true;
            break;
        case Key.Left:
            lastIndex = lvCurDocFields.SelectedIndex;
            App.StaticGabeLib.Search.SelectedDocIndex--;
            if (lvCurDocFields.SelectedIndex != lastIndex)
            {
                lvCurDocFields.SelectedIndex = lastIndex;
            }
            e.Handled = true;
            break;
    }
    base.OnPreviewKeyDown(e);
}

Upvotes: 1

Views: 791

Answers (1)

djdanlib
djdanlib

Reputation: 22566

Normally, I store a reference to the item that was selected, update the list, and re-select it afterwards. ListIndex isn't a reliable way to maintain a selection if things are inserted or deleted from the list.

if(MyListControl.Items.Contains(PreviouslySelectedItem)) MyListControl.SelectedItem = PreviouslySelectedItem;

Upvotes: 2

Related Questions