gpt4 book ai didi

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

转载 作者:IT王子 更新时间:2023-10-29 03:48:56 29 4
gpt4 key购买 nike

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

如果项目当前不可见,我希望将其滚动到我的 ListView 的中心。有没有一种简单的方法可以做到这一点?

最佳答案

使用我编写的扩展方法在 WPF 中很容易做到这一点。要将项目滚动到 View 中心,您只需调用一个方法即可。

假设您有这个 XAML:

<ListView x:Name="view" ItemsSource="{Binding Data}" /> 
<ComboBox x:Name="box" ItemsSource="{Binding Data}"
SelectionChanged="ScrollIntoView" />

您的 ScrollIntoView 方法将很简单:

private void ScrollIntoView(object sender, SelectionChangedEventArgs e)
{
view.ScrollToCenterOfView(box.SelectedItem);
}

显然,这也可以使用 ViewModel 来完成,而不是显式引用控件。

下面是实现。它非常通用,处理所有 IScrollInfo 可能性。它适用于 ListBox 或任何其他 ItemsControl,并适用于任何面板,包括 StackPanel、VirtualizingStackPanel、WrapPanel、DockPanel、Canvas、Grid 等。

只需将其放入项目中某处的 .cs 文件中即可:

public static class ItemsControlExtensions
{
public static void ScrollToCenterOfView(this ItemsControl itemsControl, object item)
{
// Scroll immediately if possible
if(!itemsControl.TryScrollToCenterOfView(item))
{
// Otherwise wait until everything is loaded, then scroll
if(itemsControl is ListBox) ((ListBox)itemsControl).ScrollIntoView(item);
itemsControl.Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new Action(() =>
{
itemsControl.TryScrollToCenterOfView(item);
}));
}
}

private static bool TryScrollToCenterOfView(this ItemsControl itemsControl, object item)
{
// Find the container
var container = itemsControl.ItemContainerGenerator.ContainerFromItem(item) as UIElement;
if(container==null) return false;

// Find the ScrollContentPresenter
ScrollContentPresenter presenter = null;
for(Visual vis = container; vis!=null && vis!=itemsControl; vis = VisualTreeHelper.GetParent(vis) as Visual)
if((presenter = vis as ScrollContentPresenter)!=null)
break;
if(presenter==null) return false;

// Find the IScrollInfo
var scrollInfo =
!presenter.CanContentScroll ? presenter :
presenter.Content as IScrollInfo ??
FirstVisualChild(presenter.Content as ItemsPresenter) as IScrollInfo ??
presenter;

// Compute the center point of the container relative to the scrollInfo
Size size = container.RenderSize;
Point center = container.TransformToAncestor((Visual)scrollInfo).Transform(new Point(size.Width/2, size.Height/2));
center.Y += scrollInfo.VerticalOffset;
center.X += scrollInfo.HorizontalOffset;

// Adjust for logical scrolling
if(scrollInfo is StackPanel || scrollInfo is VirtualizingStackPanel)
{
double logicalCenter = itemsControl.ItemContainerGenerator.IndexFromContainer(container) + 0.5;
Orientation orientation = scrollInfo is StackPanel ? ((StackPanel)scrollInfo).Orientation : ((VirtualizingStackPanel)scrollInfo).Orientation;
if(orientation==Orientation.Horizontal)
center.X = logicalCenter;
else
center.Y = logicalCenter;
}

// Scroll the center of the container to the center of the viewport
if(scrollInfo.CanVerticallyScroll) scrollInfo.SetVerticalOffset(CenteringOffset(center.Y, scrollInfo.ViewportHeight, scrollInfo.ExtentHeight));
if(scrollInfo.CanHorizontallyScroll) scrollInfo.SetHorizontalOffset(CenteringOffset(center.X, scrollInfo.ViewportWidth, scrollInfo.ExtentWidth));
return true;
}

private static double CenteringOffset(double center, double viewport, double extent)
{
return Math.Min(extent - viewport, Math.Max(0, center - viewport/2));
}
private static DependencyObject FirstVisualChild(Visual visual)
{
if(visual==null) return null;
if(VisualTreeHelper.GetChildrenCount(visual)==0) return null;
return VisualTreeHelper.GetChild(visual, 0);
}
}

关于c# - 使 ListView.ScrollIntoView 将项目滚动到 ListView 的中心 (C#),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2946954/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com