获取ListView项容器的好方法是什么?

时间:2019-04-11 09:26:07

标签: wpf uwp

我的问题是针对UWP,但解决方案在WPF中可能相同,因此我也对此进行了标记。

我正在尝试在自定义GridView和ListView中实现this扩展方法,以便当选择更改时,所选项目将始终平滑地显示在视图中。

扩展方法效果很好。但是,获取UIElement容器以发送它并不是很好。

ListView.Items绑定到ViewModel中的集合。因此ListView.Items不是UIElement,而是数据对象。我需要SelectedItem的对应UIElement容器。

首先,我尝试了这一点:

void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    if (_scrollViewer != null && this.ItemsPanelRoot != null && this.Items.Count > 0)
    {
        var selectedListViewItem = this.ItemsPanelRoot.Children[this.SelectedIndex];
        if (selectedListViewItem != null)
        {
            _scrollViewer.ScrollToElement(selectedListViewItem);
        }
    }
}

这起初是有效的,但实际上是不好的。随着布局的动态更新,“ ListView.ItemsPanelRoot.Children”的索引最终开始偏离“ ListView.Items”。

然后我尝试了这一点,到目前为止看来还不错:

void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    if (_scrollViewer != null && this.Items.Count > 0)
    {
        var selectedListViewItem = this.ItemsPanelRoot.FindDescendants<ListViewItem>()
                        .Where(x => x.Content == this.SelectedItem).FirstOrDefault();
        if (selectedListViewItem != null)
        {
            _scrollViewer.ScrollToElement(selectedListViewItem);
        }
        else
        {
            throw new Exception();
        }
    }
}

问题在于,每次执行该查询似乎都非常昂贵,而且不安全,因为无法确定容器是否可用。我感到(希望)我想念一些东西,并且有适当的方法可以做到这一点。

注意:'FindDescendants'是Windows UI Toolkit的扩展方法,与VisualTreeHelper的作用相同。

1 个答案:

答案 0 :(得分:1)

ItemsControls具有Item​Container​Generator属性,该属性包含一个ItemContainerGenerator对象,您可以使用该对象获取项目和项目索引等的项目容器。

例如

var container = listView.ItemContainerGenerator.ContainerFromItem(item);

在UWP中,ContainerFromItem和类似方法也可以直接在ItemsControl类中使用,以便您可以编写

var container = listView.ContainerFromItem(item);