【问题标题】:Programmatically Scrolling always not working以编程方式滚动总是不起作用
【发布时间】:2018-07-10 00:06:32
【问题描述】:

XAML

<Page
    x:Class="ScrollViewWithDifferentTypeOfContent.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:ScrollViewWithDifferentTypeOfContent"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

    <Grid Height="300">
        <ScrollViewer Name="MainScrollViewer"
                      IsVerticalRailEnabled="True"
                      VerticalScrollMode="Enabled"
                    >
            <StackPanel>
                <Image Source="/Assets/icon0.png" />
                <TextBlock Name="BlockyThing">  HELLO WORLD</TextBlock>
                <ListView Name="MyListView" ItemsSource="{x:Bind obsList}" Loaded="Page_Loaded">
                    <ListView.ItemTemplate>
                        <DataTemplate x:DataType="local:Item">
                            <StackPanel>
                                <TextBlock  Text="{x:Bind Message}"/>
                            </StackPanel>
                        </DataTemplate>
                    </ListView.ItemTemplate>
                </ListView>
            </StackPanel>
        </ScrollViewer>
    </Grid>
</Page>

xaml.cs 中的代码

  public static void ScrollToElement(this ScrollViewer scrollViewer, UIElement element,
        bool isVerticalScrolling = true, bool smoothScrolling = true, float? zoomFactor = null)
    {
        var transform = element.TransformToVisual((UIElement)scrollViewer.Content);
        var position = transform.TransformPoint(new Point(0, 0));

        if (isVerticalScrolling)
        {
            scrollViewer.ChangeView(null, position.Y, zoomFactor, !smoothScrolling);
        }
        else
        {
            scrollViewer.ChangeView(position.X, null, zoomFactor, !smoothScrolling);
        }
    }



namespace ScrollViewWithDifferentTypeOfContent
{
   public class Item
    {
        public string ItemName;
        public string Message;
        public static int itemNo = 0; 

        public Item()
        {
            Message = (itemNo).ToString() +  "  HELLO HELLO HELLO!!";
            ItemName = "Item" + (itemNo++);
            Debug.WriteLine(ItemName);
        }
    }

    public sealed partial class MainPage : Page
    {

        public ObservableCollection<Item> obsList = new ObservableCollection<Item>();

        public MainPage()
        {
            for(int i=0; i<40; i++)
                obsList.Add(new Item());            
            this.InitializeComponent();
        }

        private void Page_Loaded(object sender, RoutedEventArgs e)
        {
            CoreDispatcher dispatcher = Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher;

            var ignored = dispatcher.RunAsync(CoreDispatcherPriority.High, () => {
            var TEST3 = MyListView.ContainerFromIndex(4);  
            MainScrollViewer.ScrollToElement((UIElement) TEST3);
            MainScrollViewer.UpdateLayout();          
            });
        }
    }
}

嗨,在这段代码中,ScrollViewer 中有一个图像、一个文本框和一个列表视图,我试图滚动到 listView (MyListView) 中的一个项目,但这段代码有效,但有时它会滚动到指定的项目,有时它没有,我知道它可能与线程有关,但是我希望该操作始终在页面中的每个元素加载后发生。

为什么我想要这个:

我需要通过滚动页面来实现导航,

页面在列表视图之前有几个元素,但是我需要相对于列表视图元素滚动。

如何确保滚动总是发生。

【问题讨论】:

    标签: c# multithreading uwp uwp-xaml


    【解决方案1】:

    不建议在 ScrollViewer 中使用 ListView,因为这会破坏列表的虚拟化(将呈现所有 40 个项目)。

    您可以使用 HeaderTemplate 获得相同的视觉效果:

    <Grid Height="300">
        <ListView Name="MyListView"
                  ItemsSource="{x:Bind obsList}"
                  Loaded="Page_Loaded">
            <ListView.HeaderTemplate>
                <DataTemplate>
                    <StackPanel>
                        <Image Source="/Assets/icon0.png" />
                        <TextBlock Name="BlockyThing">  HELLO WORLD</TextBlock>
                    </StackPanel>
                </DataTemplate>
            </ListView.HeaderTemplate>
            <ListView.ItemTemplate>
                <DataTemplate x:DataType="local:Item">
                    <StackPanel>
                        <TextBlock  Text="{x:Bind Message}" />
                    </StackPanel>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </Grid>
    

    然后您可以从代码隐藏中调用 ScrollIntoView 方法,这可能更健壮:

    MyListView.ScrollIntoView(obsList[4]);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-11-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多