Had*_*ady 4 c# windows-runtime winrt-xaml windows-store-apps
我试图将一个选定的项目放在ScrollViewer内的ListView中心,并努力计算我应该相对于ListView设置ScrollViewer的垂直偏移量.
以下链接为我设置了正确的轨道,但由于WinRT API的限制,无法使用它们:
期望的效果如下:

这是我的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>
Run Code Online (Sandbox Code Playgroud)
知道所选项目的索引,如何计算我可以在我的方法中使用的垂直偏移量:
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);
}
Run Code Online (Sandbox Code Playgroud)
尝试ListView.ScrollIntoView()或ListView.MakeVisible首先将项目的容器滚动到视图中并解决它可能从UI虚拟化.然后使用()来获取项目的容器,然后使用
它来获取相对于该项目的位置.然后按计算的偏移滚动滚动查看器.ListView.ItemContainerGenerator.ContainerFromIndexVisualTreeHelperScrollViewer
*编辑 - 示例定位逻辑:
从WinRT XAML Toolkit 获取VisualTreeHelperExtensions以获取对包含一些调用的扩展方法的ScrollViewer轻松访问.GetFirstDescendantOfType()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>
Run Code Online (Sandbox Code Playgroud)
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());
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
10489 次 |
| 最近记录: |