使ListView.ScrollIntoView滚动项目到ListView(C#)的中心

ListView.ScrollIntoView(object)当前在中找到一个对象ListView并滚动到该对象。如果您位于要滚动到的对象下方,它将滚动该对象到第一行。如果您位于上方,则将其滚动到底部行的视图中。

如果当前不可见,我想使该项目滚动到列表视图的中心。有没有简单的方法可以做到这一点?


临摹微笑
浏览 814回答 3
3回答

撒科打诨

在WPF中使用我编写的扩展方法很容易做到这一点。将项目滚动到视图中心所需要做的就是调用一个方法。假设您有以下XAML:<ListView x:Name="view" ItemsSource="{Binding Data}" />&nbsp;<ComboBox x:Name="box"&nbsp; ItemsSource="{Binding Data}"&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SelectionChanged="ScrollIntoView" />&nbsp;您的ScrollIntoView方法将很简单:private void ScrollIntoView(object sender, SelectionChangedEventArgs e){&nbsp; view.ScrollToCenterOfView(box.SelectedItem);}&nbsp;显然,这也可以使用ViewModel来完成,而不是显式地引用控件。以下是实现。非常通用,可以处理所有IScrollInfo可能性。它可以与ListBox或任何其他ItemsControl一起使用,并且可以与任何面板一起使用,包括StackPanel,VirtualizingStackPanel,WrapPanel,DockPanel,Canvas,Grid等。只需将其放入项目中某个.cs文件中即可:public static class ItemsControlExtensions{&nbsp; public static void ScrollToCenterOfView(this ItemsControl itemsControl, object item)&nbsp; {&nbsp; &nbsp; // Scroll immediately if possible&nbsp; &nbsp; if(!itemsControl.TryScrollToCenterOfView(item))&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; // Otherwise wait until everything is loaded, then scroll&nbsp; &nbsp; &nbsp; if(itemsControl is ListBox) ((ListBox)itemsControl).ScrollIntoView(item);&nbsp; &nbsp; &nbsp; itemsControl.Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new Action(() =>&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; itemsControl.TryScrollToCenterOfView(item);&nbsp; &nbsp; &nbsp; &nbsp; }));&nbsp; &nbsp; }&nbsp; }&nbsp; private static bool TryScrollToCenterOfView(this ItemsControl itemsControl, object item)&nbsp; {&nbsp; &nbsp; // Find the container&nbsp; &nbsp; var container = itemsControl.ItemContainerGenerator.ContainerFromItem(item) as UIElement;&nbsp; &nbsp; if(container==null) return false;&nbsp; &nbsp; // Find the ScrollContentPresenter&nbsp; &nbsp; ScrollContentPresenter presenter = null;&nbsp; &nbsp; for(Visual vis = container; vis!=null && vis!=itemsControl; vis = VisualTreeHelper.GetParent(vis) as Visual)&nbsp; &nbsp; &nbsp; if((presenter = vis as ScrollContentPresenter)!=null)&nbsp; &nbsp; &nbsp; &nbsp; break;&nbsp; &nbsp; if(presenter==null) return false;&nbsp; &nbsp; // Find the IScrollInfo&nbsp; &nbsp; var scrollInfo =&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; !presenter.CanContentScroll ? presenter :&nbsp; &nbsp; &nbsp; &nbsp; presenter.Content as IScrollInfo ??&nbsp; &nbsp; &nbsp; &nbsp; FirstVisualChild(presenter.Content as ItemsPresenter) as IScrollInfo ??&nbsp; &nbsp; &nbsp; &nbsp; presenter;&nbsp; &nbsp; // Compute the center point of the container relative to the scrollInfo&nbsp; &nbsp; Size size = container.RenderSize;&nbsp; &nbsp; Point center = container.TransformToAncestor((Visual)scrollInfo).Transform(new Point(size.Width/2, size.Height/2));&nbsp; &nbsp; center.Y += scrollInfo.VerticalOffset;&nbsp; &nbsp; center.X += scrollInfo.HorizontalOffset;&nbsp; &nbsp; // Adjust for logical scrolling&nbsp; &nbsp; if(scrollInfo is StackPanel || scrollInfo is VirtualizingStackPanel)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; double logicalCenter = itemsControl.ItemContainerGenerator.IndexFromContainer(container) + 0.5;&nbsp; &nbsp; &nbsp; Orientation orientation = scrollInfo is StackPanel ? ((StackPanel)scrollInfo).Orientation : ((VirtualizingStackPanel)scrollInfo).Orientation;&nbsp; &nbsp; &nbsp; if(orientation==Orientation.Horizontal)&nbsp; &nbsp; &nbsp; &nbsp; center.X = logicalCenter;&nbsp; &nbsp; &nbsp; else&nbsp; &nbsp; &nbsp; &nbsp; center.Y = logicalCenter;&nbsp; &nbsp; }&nbsp; &nbsp; // Scroll the center of the container to the center of the viewport&nbsp; &nbsp; if(scrollInfo.CanVerticallyScroll) scrollInfo.SetVerticalOffset(CenteringOffset(center.Y, scrollInfo.ViewportHeight, scrollInfo.ExtentHeight));&nbsp; &nbsp; if(scrollInfo.CanHorizontallyScroll) scrollInfo.SetHorizontalOffset(CenteringOffset(center.X, scrollInfo.ViewportWidth, scrollInfo.ExtentWidth));&nbsp; &nbsp; return true;&nbsp; }&nbsp; private static double CenteringOffset(double center, double viewport, double extent)&nbsp; {&nbsp; &nbsp; return Math.Min(extent - viewport, Math.Max(0, center - viewport/2));&nbsp; }&nbsp; private static DependencyObject FirstVisualChild(Visual visual)&nbsp; {&nbsp; &nbsp; if(visual==null) return null;&nbsp; &nbsp; if(VisualTreeHelper.GetChildrenCount(visual)==0) return null;&nbsp; &nbsp; return VisualTreeHelper.GetChild(visual, 0);&nbsp; }}

汪汪一只猫

上面的Ray Burns出色的答案是WPF特有的。这是在Silverlight中可以使用的修改后的版本:&nbsp;public static class ItemsControlExtensions&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; public static void ScrollToCenterOfView(this ItemsControl itemsControl, object item)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Scroll immediately if possible&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (!itemsControl.TryScrollToCenterOfView(item))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Otherwise wait until everything is loaded, then scroll&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (itemsControl is ListBox) ((ListBox)itemsControl).ScrollIntoView(item);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; itemsControl.Dispatcher.BeginInvoke( new Action(() =>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; itemsControl.TryScrollToCenterOfView(item);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }));&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; private static bool TryScrollToCenterOfView(this ItemsControl itemsControl, object item)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Find the container&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var container = itemsControl.ItemContainerGenerator.ContainerFromItem(item) as UIElement;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (container == null) return false;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Find the ScrollContentPresenter&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ScrollContentPresenter presenter = null;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for (UIElement vis = container; vis != null ; vis = VisualTreeHelper.GetParent(vis) as UIElement)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if ((presenter = vis as ScrollContentPresenter) != null)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (presenter == null) return false;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Find the IScrollInfo&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var scrollInfo =&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !presenter.CanVerticallyScroll ? presenter :&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; presenter.Content as IScrollInfo ??&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FirstVisualChild(presenter.Content as ItemsPresenter) as IScrollInfo ??&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; presenter;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Compute the center point of the container relative to the scrollInfo&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Size size = container.RenderSize;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Point center = container.TransformToVisual((UIElement)scrollInfo).Transform(new Point(size.Width / 2, size.Height / 2));&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; center.Y += scrollInfo.VerticalOffset;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; center.X += scrollInfo.HorizontalOffset;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Adjust for logical scrolling&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (scrollInfo is StackPanel || scrollInfo is VirtualizingStackPanel)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; double logicalCenter = itemsControl.ItemContainerGenerator.IndexFromContainer(container) + 0.5;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Orientation orientation = scrollInfo is StackPanel ? ((StackPanel)scrollInfo).Orientation : ((VirtualizingStackPanel)scrollInfo).Orientation;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (orientation == Orientation.Horizontal)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; center.X = logicalCenter;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; else&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; center.Y = logicalCenter;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Scroll the center of the container to the center of the viewport&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (scrollInfo.CanVerticallyScroll) scrollInfo.SetVerticalOffset(CenteringOffset(center.Y, scrollInfo.ViewportHeight, scrollInfo.ExtentHeight));&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (scrollInfo.CanHorizontallyScroll) scrollInfo.SetHorizontalOffset(CenteringOffset(center.X, scrollInfo.ViewportWidth, scrollInfo.ExtentWidth));&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return true;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; private static double CenteringOffset(double center, double viewport, double extent)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return Math.Min(extent - viewport, Math.Max(0, center - viewport / 2));&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; private static DependencyObject FirstVisualChild(UIElement visual)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (visual == null) return null;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (VisualTreeHelper.GetChildrenCount(visual) == 0) return null;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return VisualTreeHelper.GetChild(visual, 0);&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp;
打开App,查看更多内容
随时随地看视频慕课网APP