1

我已经实现了一个运行良好的虚拟化面板,该面板实现了 IScrollInfo。我正在使用键盘让它工作。Panel 在 ListView 中用作 ListView.ItemsPanel。当用户按下所选项目正确更改但不滚动时,当您到达最后一个可见项目时,您不能再按下。我试图弄清楚如何让面板知道所选项目并适当地滚动。我尝试过四处搜索,但似乎找不到与我想做的事情相关的任何事情。一个正确方向的点将不胜感激。

编辑:是 VirtualizingWrapPanel 的代码

4

1 回答 1

0

所以我找到了一个效果很好的解决方案,我不确定它是否是最好的方法,但它似乎工作正常。

在遍历子项时的 ArrangeOverride 方法中,我执行以下操作。

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

在 MeasureOverride 中,我在这里调用 CleanUpItems,我们需要取消订阅所选事件。

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

我还添加了以下三个功能。

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;
}

GetOffsetForFirstVisibleIndex 函数可能会根据您的实现而有所不同,但如果其他人在想出解决方案时遇到问题,这应该是足够的信息。

于 2013-09-08T16:06:50.320 回答