定心在涡旋观众选择项 [英] Centering selected item in a scroll viewer

查看:142
本文介绍了定心在涡旋观众选择项的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在的ScrollViewer内的ListView到中心选定的项目,并奋力计算垂直偏移,我应该在的ScrollViewer相对于ListView控件进行设置。



以下链接让我在正确的轨道上,但由于的WinRT API的限制,无法使用它们:





期望的效果如下:



中的ScrollViewer中心选定的项目



这是我的XAML示例设置:

 <的ScrollViewer X:NAME =MyScrollViewer> 
< ListView的X:名称=MyView的VerticalAlignment =中心
的SelectionChanged =Selector_OnSelectionChanged>
< ListView.ItemTemplate>
<&DataTemplate的GT;
<电网WIDTH =80HEIGHT =80保证金=0>
< TextBlock的文本={结合}/>
< /网格和GT;
< / DataTemplate中>
< /ListView.ItemTemplate>
< ListView.Items>
将; X:字符串→1&下; / X:字符串>
将; X:字符串→2&下; / X:字符串>
将; X:字符串→3&下; / X:字符串>
将; X:字符串→4&下; / X:字符串>
将; X:字符串> 5℃/ X:字符串>
将; X:字符串→6&下; / X:字符串>
将; X:字符串大于7&下; / X:字符串>
将; X:字符串→8&下; / X:字符串>
< X:字符串> 9< / X:字符串>
< /ListView.Items>
< /&的ListView GT;
< /&的ScrollViewer GT;



了解所选项目的索引,我该如何计算垂直偏移,我可以用我的方法:

  Selector_OnSelectionChanged私人无效(对象发件人,SelectionChangedEventArgs E)
{
双maxVerticalOffset = MyScrollViewer。 ExtentHeight - MyScrollViewer.ViewportHeight;

INT selectedItemIndex = MyView.SelectedIndex;

双verticalOffset = ...

MyScrollViewer.ChangeView(NULL,verticalOffset,NULL);
}


解决方案

尝试的 ListView.ScrollIntoView() ListView.MakeVisible 第一个项目的容器滚动到视图和工作围绕它可能正在从虚拟化的UI。然后使用
ListView.ItemContainerGenerator ContainerFromIndex ()获得该项目的容器,然后在 VisualTreeHelper 来获取相对于的ScrollViewer 的位置。然后滚动通过将计算抵消的ScrollViewer



*编辑 - 举例定位逻辑:



获得<一个HREF =https://winrtxamltoolkit.codeplex.com/SourceControl/latest#WinRTXamlToolkit/WinRTXamlToolkit.Shared/Controls/Extensions/VisualTreeHelperExtensions.cs相对=nofollow> VisualTreeHelperExtensions从WinRT的XAML工具包来获得访问在的ScrollViewer 容易与封装到 VisualTreeHelper GetFirstDescendantOfType()扩展方法code>。



XAML

 <第
X:类=ListViewItemCentering.MainPage
的xmlns =http://schemas.microsoft.com/winfx/2006/xaml/presentation
的xmlns:X =http://schemas.microsoft.com/winfx/2006/xaml
的xmlns:本地=使用:ListViewItemCentering
的xmlns:D =http://schemas.microsoft.com/表达/混合/ 2008
的xmlns:MC =http://schemas.openxmlformats.org/markup-compatibility/2006
MC:可忽略=D>

<电网
背景={ThemeResource ApplicationPageBackgroundThemeBrush}>
< ListView的
X:NAME =ListView控件>
< ListView.ItemTemplate>
<&DataTemplate的GT;
< BORDER
WIDTH =400
HEIGHT =100>
< ContentControl中
含量={结合}
字号=48
填充=20,10/>
< /边框>
< / DataTemplate中>
< /ListView.ItemTemplate>
< /&的ListView GT;

<按钮
含量=跳过
WIDTH =200
HEIGHT =100
的Horizo​​ntalAlignment =右
VerticalAlignment =底
点击=ButtonBase_OnClick/>
< /网格和GT;
< /页>



C#



 使用系统; 
使用System.Collections.Generic;
使用System.Linq的;使用System.Threading.Tasks
;
使用Windows.Foundation;
使用Windows.UI.Xaml;使用Windows.UI.Xaml.Controls
;使用WinRTXamlToolkit.Controls.Extensions
;

命名空间ListViewItemCentering
{
///<总结>
///可以在自己的一个框架内使用或导航到一个空白页。
///< /总结>
公共密封部分类的MainPage:第
{
私人随机随机=新的随机();
公众的MainPage()
{
this.InitializeComponent();
this.listView.ItemsSource = Enumerable.Range(1,1000);
this.listView.SelectionChanged + = OnListViewSelectionChanged;
}

私人异步无效OnListViewSelectionChanged(对象发件人,SelectionChangedEventArgs selectionChangedEventArgs)
{
如果(listView.SelectedItem == NULL)
{
返回;
}

VAR项目= listView.SelectedItem;

//计算相对于屏幕或ListView
VAR的ListViewItem =(FrameworkElement的)listView.ContainerFromItem(项目);

如果(ListViewItem的== NULL)
{
listView.ScrollIntoView(项目);
}

,而(ListViewItem的== NULL)
{
等待Task.Delay(1); //等待滚动完成 - 它需要一段时间
的ListViewItem =(FrameworkElement的)listView.ContainerFromItem(项目);
}

变种左上=
ListViewItem的
.TransformToVisual(ListView控件)
.TransformPoint(新点())Y。
VAR lvih = listViewItem.ActualHeight;
VAR肥厚= listView.ActualHeight;
VAR desiredTopLeft =(LVH - lvih)/ 2.0;
VAR desiredDelta =左上 - desiredTopLeft;

//计算相对ListView的
VAR内向的ScrollViewer的ScrollViewer = listView.GetFirstDescendantOfType<&的ScrollViewer GT;();
VAR currentOffset = scrollViewer.VerticalOffset;
VAR desiredOffset = currentOffset + desiredDelta;
scrollViewer.ScrollToVerticalOffset(desiredOffset);

//更好,但如果建设为Windows 8.1,使滚动更流畅的使用:
// scrollViewer.ChangeView(NULL,desiredOffset,NULL);
}

私人异步无效ButtonBase_OnClick(对象发件人,RoutedEventArgs E)
{
this.listView.SelectedIndex = random.Next(0,((IEnumerable的< INT> ;)this.listView.ItemsSource).Count之间的());
}
}
}


I am trying to center a selected item in a ListView inside a ScrollViewer and struggling to calculate the vertical offset that I should be setting the ScrollViewer relative to the ListView.

The following links set me on the right track, but because of the limitation of the WinRT API, was not able to use them:

The desired effect is as follows:

This is a sample setup in my 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>

Knowing the index of the selected item, how do I calculate the vertical offset that I can use in my method:

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);
}

解决方案

Try ListView.ScrollIntoView() or ListView.MakeVisible first to scroll the container of the item into view and work around it being possibly virtualized out of the UI. Then use ListView.ItemContainerGenerator.ContainerFromIndex() to get the container of the item and then the VisualTreeHelper to get its position relative to the ScrollViewer. Then scroll the scrollviewer by the calculated offset.

*EDIT - Example positioning logic:

Get the VisualTreeHelperExtensions from WinRT XAML Toolkit to get access to the ScrollViewer easily with GetFirstDescendantOfType() extension method that wraps some calls to the 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());
        }
    }
}

这篇关于定心在涡旋观众选择项的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆