【问题标题】:UWP ScrollViewer unexpected behaviorUWP ScrollViewer 意外行为
【发布时间】:2018-09-17 16:14:36
【问题描述】:

在为 UWP 平台开发应用程序时,我遇到了一个意外行为的案例。当我在一个页面上展示的内容太多时,我利用了 ScrollViewer 控件,它应该可以解决这个问题。

该控件允许滚动内容,但它处理输入的方式不自然。当控件被 Clicked 时,ScrollViewer 中没有可聚焦的控件被点击,Focus 被传递给其内容中的第一个可聚焦的控件.这实际上意味着 ScrollViewer 滚动回顶部,这不是我所期望的行为。

我希望 ScrollViewer 保持其当前位置,就像网页一样。如果要单击空白处,则网页不会滚动回第一个可聚焦控件。另一个类似的例子是 GridStackpanel 在单击时不会将焦点传递给它的其中一个子项。

下面是一些演示上述行为的 xaml 代码,只需创建一个新的 UWP 项目 并将其放置在生成的 MainPage.xaml 的网格中:

<ScrollViewer Height="400"> <!-- Unexpected and unnatrual behavior -->
    <StackPanel Width="250" Background="DarkGray" Padding="10"> <!-- With Content Height > ScrollViewer Height -->
        <TextBlock Text="Unnatural scroll behavior" FontWeight="Bold"/>
        <TextBox Text="Some focusable control"/>
        <TextBlock Height="800" Text="On focus => pass focus to first available => scroll to the top" TextWrapping="Wrap"/>
        <TextBox Text="Some focusable control"/>
    </StackPanel>
</ScrollViewer>

我确实想出了一个解决方案,但是这似乎是解决当前问题的正确方法,这似乎很奇怪:

<ScrollViewer Height="400">
    <!-- Corrected behaviour, but extra ContentControl. Easily forgotten -->
    <ContentControl>
        <StackPanel Width="250" Background="Gray" Padding="10">
            <!-- With Content Height > ScrollViewer Height -->
            <TextBlock Text="Corrected scroll behavior" FontWeight="Bold"/>
            <TextBox Text="Some focusable control"/>
            <TextBlock Height="800" Text="On focus => no scroll" TextWrapping="Wrap"/>
            <TextBox Text="Some focusable control"/>
        </StackPanel>
    </ContentControl>
</ScrollViewer>

这可行,但是总是记得添加 ContentControl 很烦人,这就是为什么我会发布一个以更好的方式实现我的解决方案的答案。

问题仍然存在:有没有更好的方法来解决这个问题?

【问题讨论】:

    标签: c# xaml uwp scrollviewer


    【解决方案1】:

    我的解决方案通过创建一个处理 ContentControl 的自定义 UserControl 以对开发人员更友好的方式实现。

    Scroller.xaml:

    <UserControl
        x:Class="Controls.Scroller"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        d:DesignHeight="300"
        d:DesignWidth="400">
    
        <ScrollViewer Name="ScrollerControl" Height="{x:Bind Height, Mode=TwoWay}" Width="{x:Bind Width, Mode=TwoWay}">
            <ContentControl Content="{x:Bind ScrollContent}"/>
        </ScrollViewer>
    
    </UserControl>
    

    Scroller.xaml.cs:

    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Controls;
    using Windows.UI.Xaml.Markup;
    
    namespace Controls
    {
        [ContentProperty(Name = "ScrollContent")]
        public sealed partial class Scroller : UserControl
        {
            public static readonly DependencyProperty ScrollContentProperty = DependencyProperty.Register("ScrollContent", typeof(object), typeof(object), new PropertyMetadata(new Grid()));
    
            public ScrollViewer ScrollViewer { get { return ScrollerControl; } }
            public object ScrollContent { get { return GetValue(ScrollContentProperty); } set { SetValue(ScrollContentProperty, value); } }
    
            public Scroller()
            {
                DataContext = this;
                this.InitializeComponent();
            }
        }
    }
    

    用法:

    首先将以下行添加到页面的 xaml:

    xmlns:cont="using:Controls"
    

    然后按如下方式使用控件:

    <cont:Scroller Height="400" x:Name="ScrollControl">
        <!-- Place any content in here -->
        <!-- The content below is just for example -->
        <StackPanel Width="250" Background="DarkGray" Padding="10">
            <TextBlock Text="Corrected scroll behaviour" FontWeight="Bold"/>
            <TextBox Text="Some focusable control"/>
            <TextBlock Height="800" Text="On focus => no scroll" TextWrapping="Wrap"/>
            <TextBox Text="Some focusable control"/>
        </StackPanel>
    </cont:Scroller>
    

    请注意,必须使用 x:Name 来引用代码中的控件。此外,如果您想访问 ScrollViewer,请使用

    ScrollControl.ScrollViewer
    

    【讨论】:

    • @CoCaIceDew 我首先没有选中它,因为我想等待大约一周,看看是否有人对所提出的问题有更好的解决方案。但是我确实忘记接受我的解决方案,所以谢谢提醒!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-05-12
    • 2017-11-16
    • 1970-01-01
    • 2016-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多