我的问题是针对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的作用相同。
答案 0 :(得分:1)
ItemsControls具有ItemContainerGenerator
属性,该属性包含一个ItemContainerGenerator对象,您可以使用该对象获取项目和项目索引等的项目容器。
例如
var container = listView.ItemContainerGenerator.ContainerFromItem(item);
在UWP中,ContainerFromItem
和类似方法也可以直接在ItemsControl类中使用,以便您可以编写
var container = listView.ContainerFromItem(item);