【问题标题】:Scroll ListViewItem to be at the top of a ListView滚动 ListViewItem 到 ListView 的顶部
【发布时间】:2009-07-03 00:57:44
【问题描述】:

在 WPF 中,我知道我可以使用 ListView.ScrollIntoView 将特定项目滚动到视图中,但它总是会做最少的滚动以便显示项目。

如何让它滚动,以便我要显示的项目滚动到 ListView 的顶部?

我考虑过调用 ScrollIntoView 两次,一次用于我想要在顶部的项目,一次用于最后显示的项目,但我不知道如何找出最后显示的项目。

【问题讨论】:

    标签: wpf listview scroll


    【解决方案1】:

    我们可以通过获取 ListView 的 ControlTemplate 中存在的ScrollViewer 来做到这一点。如果您可以访问 ScrollViewer,则有 a lot 暴露了不同的滚动方法。

    首先,我们可以创建一个 ListView 来添加这个效果:

    <ListView ItemsSource="{Binding Percents}"
          SelectionChanged="OnSelectionChanged"
          x:Name="uiListView"/>
    


    public List<int> Percents { get; set; }
    
    public Window1()
    {
        InitializeComponent();
    
        Percents = new List<int>();
        for (int i = 1; i <= 100; i++)
        {
            Percents.Add(i);
        }
        this.DataContext = this;
    }
    

    我们还需要一些可以用来从 ListView 获取 ScrollViewer 的东西。我之前使用过类似的东西来处理自定义滚动,我们也可以在这里使用它。

    public static DependencyObject GetScrollViewer(DependencyObject o)
    {
        if (o is ScrollViewer)
        { return o; }
    
        for (int i = 0; i < VisualTreeHelper.GetChildrenCount(o); i++)
        {
            var child = VisualTreeHelper.GetChild(o, i);
    
            var result = GetScrollViewer(child);
            if (result == null)
            {
                continue;
            }
            else
            {
                return result;
            }
        }
    
        return null;
    }
    

    现在,我们只需要处理 SelectionChanged 事件。因为我们试图将一个项目滚动到列表的顶部,所以最好的选择是滚动到底部,然后重新向上滚动到我们选择的项目。正如您所说,ScrollIntoView 将一直滚动到该项目可见为止,因此一旦选定的项目在向上滚动时到达顶部,它将停止将我们选定的项目留在列表的最顶部。

    private void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        ScrollViewer scrollViewer = GetScrollViewer(uiListView) as ScrollViewer;
        scrollViewer.ScrollToBottom();
    
        uiListView.ScrollIntoView(e.AddedItems[0]);
    }
    

    【讨论】:

    • 注意,如果您使用的是 WPF 扩展工具包,您可以在一行代码中获取 ScrollViewer:VisualTreeHelperEx.FindDescendantByType(YourListView);
    • 好@Mr.Bungle!只需添加一点:VisualTreeHelperEx 在 Xceed.Wpf.Toolkit.Core.Utilities 命名空间中。不得不挖一点才能找到那么深;-)
    【解决方案2】:

    这是@rmoore 的答案的替代方案,即避免滚动到底部。另请注意,这仅在SelectionMode=Single 的情况下有用。

    如果ScrollViewer.CanContentScroll=True ScrollViewer 可以直接滚动到SelectedIndex。

    private void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        ScrollViewer scrollViewer = GetScrollViewer(uiListView) as ScrollViewer;      
        scrollViewer.ScrollToVerticalOffset(listView.SelectedIndex);
    }
    

    如果ScrollViewer.CanContentScroll=False 需要一些额外的 XAML:

    <ListView ScrollViewer.CanContentScroll="False" ItemsSource="{Binding Percents}" x:Name="uiListView">
        <ListView.ItemContainerStyle>
            <Style TargetType="{x:Type ListViewItem}">
                <EventSetter Event="Selected" Handler="OnSelected"/>
            </Style>
         </ListView.ItemContainerStyle>
    </ListView>
    

    并且ScrollViewer可以移动到ListViewItem顶部的垂直偏移。

    private void OnSelected(object sender, RoutedEventArgs e)
    {
        ScrollViewer scrollViewer = GetScrollViewer(uiListView) as ScrollViewer;      
    
        ListViewItem listViewItem = (ListViewItem)e.Source;
        Point offset = listViewItem.TranslatePoint(new Point(), scrollViewer);
        scrollViewer.ScrollToVerticalOffset(scrollViewer.VerticalOffset + offset.Y);
    }
    

    【讨论】:

      猜你喜欢
      • 2011-02-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-24
      • 1970-01-01
      相关资源
      最近更新 更多