8

我有一个 WinRT/C#/XAML 应用程序,其视图具有项目的垂直 ListView。根据项目的数量,ListView 会显示一个垂直滚动条。这是 XAML 定义:

<UserControl.Resources>
    <CollectionViewSource
        x:Name="myViewSource"
        Source="{Binding myViewModel.Items}" />
</UserControl.Resources>
...
<ListView
    x:Name="myListView"
    ItemsSource="{Binding Source={StaticResource myViewSource}}"
    SelectedItem="{Binding SelectedItem, Mode=TwoWay}">
</ListView>

现在,每次我导航到该视图时,ListView 的选定项都是通过从后面的代码 ( OnNavigatedTo) 中设置视图模型中的数据绑定 SelectedItem 属性来选择的。我的问题: ListView 不会自动滚动到这个选定的项目。滚动条保留在 ListView 的顶部,用户必须手动滚动才能看到所选项目。

我在后面的代码中设置了 SelectedItem 后尝试执行myListView.ScrollIntoView(MyViewModel.SelectedItem);(in OnNavigatedTo),但它不起作用。滚动条保持在顶部。

我知道 SO 上的这个线程:Scroll WinRT ListView to specific group。这似乎是一个类似的问题。但是,当我手动或使用 WinRT XAML 工具包遍历 ListView 的可视化树时,它找不到 ScrollViewer(而是返回 null)。

4

2 回答 2

18

Thanks to Filip I noticed that calling ScrollIntoView() in OnNavigatedTo() was too early, because the ListView control is not loaded yet in this place.

The first solution idea was to bind the Loaded event of the ListView:

myListView.Loaded += (s, e) => 
    myListView.ScrollIntoView(MyViewModel.SelectedItem);

Unfortunately that causes a nasty visual effect, where current ListView items overlap with the selected item for parts of a second, before everything is rearranged well.

The final solution I found is to call ScrollIntoView() asynchronously via the Dispatcher of the view:

myListView.Loaded += (s, e) => Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
    () => myListView.ScrollIntoView(MyViewModel.SelectedItem));

With this solution the layouting works fine.

于 2012-08-27T07:18:38.117 回答
4

我有类似的需求,并以稍微不同的方式解决了它。我从 ListView 订阅了 SelectionChangedEvent 并在处理程序中执行了滚动。

XAML:

<ListView x:Name="myListView" SelectionChanged="myListView_SelectionChanged" ...>
</ListView>

代码:

private void myListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    myListView.ScrollIntoView(myListView.SelectedItem);
}
于 2016-10-10T15:02:05.107 回答