Question

I have implemented a virtualizing panel that works pretty well, the panel implements IScrollInfo. I am in the process of getting it to work using a keyboard. The Panel is used in a ListView as the ListView.ItemsPanel. When the user presses down the selected item correctly changes but no scrolling occurs and when you reach the last visible item you can not press down any longer. I am trying to figure out how to have the panel aware of the selected item and scroll appropriately. I have tried searching around but I cant seem to find anything related to what I want to do. A point in the right direction would be greatly appreciated.

Edit: Here is the code for the VirtualizingWrapPanel

Was it helpful?

Solution

So I found a solution that works fairly well, I am not sure if it is the best route to take but it seems to work fine.

In the ArrangeOverride method while looping over the children I do the following.

var listViewItem = child as ListViewItem;
if (listViewItem != null)
{
    listViewItem.Selected -= ListViewItemSelected;
    listViewItem.Selected += ListViewItemSelected;
}

In MeasureOverride I make a call to CleanUpItems in here we will need to unsubscribe from the selected event.

var listViewItem = children[i] as ListViewItem;
if (listViewItem != null)
{
    listViewItem.Selected -= ListViewItemSelected;
}

I also added the following three functions.

private void ListViewItemSelected(object sender, RoutedEventArgs e)
{
    var listViewItem = sender as ListViewItem;
    if(listViewItem == null) return;

    var content = listViewItem.Content as CollectionViewGroup;
    if(content != null) return; //item is a group header dont click

    var items = ItemContainerGenerator as ItemContainerGenerator;
    if(items == null) return;
    BringIndexIntoView(items.IndexFromContainer(listViewItem));
    listViewItem.Focus();
}

protected override void BringIndexIntoView(int index)
{
    var offset = GetOffsetForFirstVisibleIndex(index);
    SetVerticalOffset(offset.Height);
}

private Size GetOffsetForFirstVisibleIndex(int index)
{
    int childrenPerRow = CalculateChildrenPerRow(_extent);
    var actualYOffset = ((index / childrenPerRow) * ChildDimension.Height) - ((ViewportHeight - ChildDimension.Height) / 2);
    if (actualYOffset < 0)
    {
        actualYOffset = 0;
    }
    Size offset = new Size(_offset.X, actualYOffset);
    return offset;
}

The GetOffsetForFirstVisibleIndex function will probably vary depending on your implementation but that should be enough info if anyone else is having trouble coming up with a solution.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top