c# – 使滚动查看器中的所选项居中
我试图将一个选定的项目放在ScrollViewer内的ListView中心,并努力计算我应该相对于ListView设置ScrollViewer的垂直偏移量.
以下链接为我设置了正确的轨道,但由于WinRT API的限制,无法使用它们: > Make ListView.ScrollIntoView Scroll the Item into the Center of the ListView (C#) 期望的效果如下: 这是我的XAML中的示例设置: <ScrollViewer x:Name="MyScrollViewer"> <ListView x:Name="MyView" VerticalAlignment="Center" SelectionChanged="Selector_OnSelectionChanged"> <ListView.ItemTemplate> <DataTemplate> <Grid Width="80" Height="80" Margin="0"> <TextBlock Text="{Binding}" /> </Grid> </DataTemplate> </ListView.ItemTemplate> <ListView.Items> <x:String>1</x:String> <x:String>2</x:String> <x:String>3</x:String> <x:String>4</x:String> <x:String>5</x:String> <x:String>6</x:String> <x:String>7</x:String> <x:String>8</x:String> <x:String>9</x:String> </ListView.Items> </ListView> </ScrollViewer> 知道所选项目的索引,如何计算我可以在我的方法中使用的垂直偏移量: private void Selector_OnSelectionChanged(object sender,SelectionChangedEventArgs e) { double maxVerticalOffset = MyScrollViewer.ExtentHeight - MyScrollViewer.ViewportHeight; int selectedItemIndex = MyView.SelectedIndex; double verticalOffset = ... MyScrollViewer.ChangeView(null,verticalOffset,null); } 解决方法
首先尝试
ListView.ScrollIntoView() 或
ListView.MakeVisible 将项目的容器滚动到视图中并解决它可能从UI虚拟化.然后用
ListView.ItemContainerGenerator .
ContainerFromIndex ()获取项目的容器,然后获取VisualTreeHelper以获取其相对于ScrollViewer的位置.然后按计算的偏移滚动滚动查看器.
*编辑 – 示例定位逻辑: 从WinRT XAML Toolkit获取VisualTreeHelperExtensions,使用GetFirstDescendantOfType()扩展方法轻松访问ScrollViewer,该方法包含对VisualTreeHelper的一些调用. XAML <Page x:Class="ListViewItemCentering.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:ListViewItemCentering" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <ListView x:Name="listView"> <ListView.ItemTemplate> <DataTemplate> <Border Width="400" Height="100"> <ContentControl Content="{Binding}" FontSize="48" Padding="20,10"/> </Border> </DataTemplate> </ListView.ItemTemplate> </ListView> <Button Content="Skip" Width="200" Height="100" HorizontalAlignment="Right" VerticalAlignment="Bottom" Click="ButtonBase_OnClick"/> </Grid> </Page> C# using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Windows.Foundation; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using WinRTXamlToolkit.Controls.Extensions; namespace ListViewItemCentering { /// <summary> /// An empty page that can be used on its own or navigated to within a Frame. /// </summary> public sealed partial class MainPage : Page { private Random random = new Random(); public MainPage() { this.InitializeComponent(); this.listView.ItemsSource = Enumerable.Range(1,1000); this.listView.SelectionChanged += OnListViewSelectionChanged; } private async void OnListViewSelectionChanged(object sender,SelectionChangedEventArgs selectionChangedEventArgs) { if (listView.SelectedItem == null) { return; } var item = listView.SelectedItem; // Calculations relative to screen or ListView var listViewItem = (FrameworkElement)listView.ContainerFromItem(item); if (listViewItem == null) { listView.ScrollIntoView(item); } while (listViewItem == null) { await Task.Delay(1); // wait for scrolling to complete - it takes a moment listViewItem = (FrameworkElement)listView.ContainerFromItem(item); } var topLeft = listViewItem .TransformToVisual(listView) .TransformPoint(new Point()).Y; var lvih = listViewItem.ActualHeight; var lvh = listView.ActualHeight; var desiredTopLeft = (lvh - lvih) / 2.0; var desiredDelta = topLeft - desiredTopLeft; // Calculations relative to the ScrollViewer within the ListView var scrollViewer = listView.GetFirstDescendantOfType<ScrollViewer>(); var currentOffset = scrollViewer.VerticalOffset; var desiredOffset = currentOffset + desiredDelta; scrollViewer.ScrollToVerticalOffset(desiredOffset); // better yet if building for Windows 8.1 to make the scrolling smoother use: // scrollViewer.ChangeView(null,desiredOffset,null); } private async void ButtonBase_OnClick(object sender,RoutedEventArgs e) { this.listView.SelectedIndex = random.Next(0,((IEnumerable<int>)this.listView.ItemsSource).Count()); } } } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |