在都市风格的XAML ScrollViewer中进行统一文本缩放

时间:2012-07-02 14:09:51

标签: xaml windows-8 microsoft-metro winrt-xaml

我一直试图在Windows 8 metro风格的应用程序中运行一些东西,而我却无法获得正确的属性。这就是我想要发生的事情:

我有一个包含StackPanel的ScrollViewer。 RichTextBox被添加到堆栈面板(来自服务器的流文本数据)。它有效地像一个控制台。所以我的布局大致如下:

<ScrollViewer>
  <StackPanel x:Name="outputStackPanel"/>
</ScrollViewer>

我希望的行为是这样的: 我希望文本在屏幕大小的水平方向上均匀缩放,然后在ScrollViewer中垂直滚动。也就是说,我使用的字体是固定宽度的字体,无论屏幕尺寸是多少,我都希望出现相同数量的ascii字符。

此外,我在应用程序中有一个选项来包装文本或不包装文本到屏幕。这意味着,当文本换行时,它应该换行到固定的屏幕宽度,但是当它不是时,ScrollViewer应该可以水平滚动,但在任何时候,滚动时水平可以看到大致相同数量的字符。

我已经尝试了几种方法来做到这一点,但没有一种方法是成功的。我试过添加一个ViewBox,如下所示:

<ScrollViewer>
  <Viewbox Stretch="UniformToFill" StretchDirection="UpOnly">
    <StackPanel x:Name="outputStackPanel" />
  </ViewBox>
</ScrollViewer>

虽然这似乎可以使文本以正确的大小显示,但是当文本换行打开时,它不允许文本换行。内容只是在右侧切断。

我目前的解决方法是检查屏幕分辨率并对字体大小进行粗略估计以使其正确显示,但这并不理想,因为它不准确,因此不同的分辨率会产生大量不同的可见字符,并且就本申请而言,可见字符的数量是显着的。

2 个答案:

答案 0 :(得分:4)

我已经能够让它发挥作用,但遗憾的是我认为没有一个可以自动适用于任何字体的答案。我可能是错的,但这是我如何让它工作:

我选择了固定宽度字体(Consolas)和特定尺寸。我觉得这个尺寸不重要。

选择字体大小后,我将RichTextBlock放入ViewBox中,并确切地想出了设置RichTextBlock所需的WIDTH,以便在屏幕上获得我想要的确切字符数(或列数)。在字体大小为13.333时,要获得正好60列,我需要宽度为440。

在ViewBox中使用13.333字体大小和固定宽度440,无论屏幕分辨率或方向如何,文本都会包含,我总能获得60列。 现在,这是有效的,我需要解决你的问题做同样的事情,禁用自动换行。

您希望文本能够从屏幕上流出并允许用户向任一方向平移,但您始终需要固定数量的列(在我的示例中为60)。为了实现这一点,我从RichTextBox中删除了固定宽度,并找出了ScrollViewer需要设置的缩放级别,以便始终获得60列宽。事实证明,缩放级别是当前屏幕宽度除以440(我为此特定字体和大小提出的神奇宽度)。

所以,这是xaml:

    <ScrollViewer x:Name="Scroller" ZoomMode="Disabled" HorizontalScrollBarVisibility="Visible" >
        <RichTextBlock x:Name="TextBlock">
            <Paragraph FontSize="13.333" FontFamily="Consolas">
                <Run Text="…" FontFamily="Consolas"/>
            </Paragraph>
        </RichTextBlock>
    </Viewbox>
</ScrollViewer>

自动换行ON:

TextBlock.Width=440
Scroller. ZoomToFactor(1.0f)

关于自动换行OFF:

TextBlock.Width=Auto
Scroller.ZoomToFactor((float)Window.Current.Bounds.Width / 440);

每当窗口大小发生变化时,更改缩放级别非常重要。这可能是因为用户旋转了设备,因为他们连接了外部显示器,因为您已进入快照视图等。只要订阅Window.Current.SizeChanged事件,您就可以收到通知。在事件内部,请务必使用传递给您的参数,因为此时窗口尚未实际更改大小。所以:

void Current_SizeChanged(object sender, Windows.UI.Core.WindowSizeChangedEventArgs e)
{
    Scroller.ZoomToFactor((float)e.Size.Width / 440);
}

最后,显然440的宽度与特定字体,字体大小以及我总是希望显示60列的事实相关联。一旦我弄明白,只要我使用相同的字体和字体大小,它就不应该在任何显示尺寸上改变。如果您想允许用户选择不同的字体,您将不得不想办法动态计算。在我20分钟的搜索中,我找不到任何答案。也许其他人可以找到它。

答案 1 :(得分:0)

您可以尝试使用Viewbox控件。它调整了内容的大小,因此您不必担心屏幕分辨率和内容。

C#的文档为here。还有一个JS版本。

here是关于扩展Metro应用程序的精彩MS指南,您可以查看其他一些想法。