在为 UWP 平台开发应用时,我遇到了一个意外行为的情况。当我在一个页面上显示太多内容时,我利用 ScrollViewer 控件,这应该可以解决这个问题。
控件允许滚动内容,但它处理输入的方式不自然。当控件获得单击,以便单击 ScrollViewer 中没有可聚焦控件时,焦点将传递给其内容中的第一个可聚焦控件。这实际上意味着 ScrollViewer 滚动回到顶部,这不是我不期望的行为。
我希望 ScrollViewer 保留当前位置,就像网页一样。如果要点击空白处,网页不会滚动回第一个可聚焦控件。另一个类似的例子是网格或 Stackpanel 在点击时不会将焦点传递给其中一个孩子。
下面是一些演示上述行为的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 非常烦人,这就是为什么我会以更好的方式发布实现我的解决方案的答案。
问题仍然存在:有没有更好的方法来解决这个问题?
答案 0 :(得分:0)
通过创建处理 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();
}
}
}
用法:
首先将以下行添加到Page的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