如何在Windows Store应用程序中显示大量文本?

6
当在WinRT中显示大量文本时,无论是在RichTextBlock还是在TextBlock中,我注意到WinRT XAML渲染引擎会达到其极限。因此,请考虑以下简单示例,其中我在XAML中定义了一个RichTextBlock,并在代码后台中使用大量文本填充它。(对于简单的TextBlock,这将类似工作。)
这是XAML部分:
<ScrollViewer>
    <RichTextBlock Name="rtb" />
</ScrollViewer>

同时还需要一些后端代码来填充它:

void MainPage_Loaded(object sender, Windows.UI.Xaml.RoutedEventArgs e)
{
    string text = Enumerable.Range(0, 200).Aggregate("", (current, i) => current + loremipsum);
    text = text.Replace("\r\n", "\n").Replace("\r", "\n");
    foreach (var line in text.Split('\n'))
    {
        var paragraph = new Paragraph();
        paragraph.Inlines.Add(new Run { Text = line });
        this.rtb.Blocks.Add(paragraph);
    }
}

private const string loremipsum = @"
    Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. 
    Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. 
    Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. 
    Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. 
    Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. ";

在第一时间看起来似乎能够正常工作,但当你开始缩放时,应用程序会冻结和崩溃,因为xaml渲染器失败了。这种情况会在没有任何交互的情况下立即发生,而且对于大量文本来说更加明显。
所以问题是:如何在WinRT中显示大量文本,其中“大量”指的是约100KB或更多甚至达到5MB的文本?
注意:我尚未尝试WebBrowser控件,因为它应该是只读的,并且我想避免复制和粘贴。所以WebBrowser控件不适合我。
编辑:
我找到了一个临时解决方案,将行添加为ItemsControl的项,其中项目是虚拟化的。
<ItemsControl Name="ItemsControl">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <VirtualizingStackPanel/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.Template>
        <ControlTemplate TargetType="ItemsControl">
            <ScrollViewer>
                <ItemsPresenter/>
            </ScrollViewer>
        </ControlTemplate>
    </ItemsControl.Template>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding}"/>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

有了这个解决方案,应用程序不再崩溃,但性能真的很差。


我建议您检查使用支持“增量加载”的备份项集合(backing item collection)。您还可以分阶段加载文本,以使其具有良好的性能和响应速度,即使文本并不是立即可用,类似于图像处理。此外,您是否一直从磁盘中读取文本?如果是,则最好在开始时将其全部加载到内存中。另外,您可能需要阅读关于这个的参考资料。也许尝试使用 ItemsStackPanel - Nate Diamond
我会结合您的虚拟化方法和将文本分成几部分的方法来使用。 - khamitimur
1个回答

1

准备好使用Win2D了。下面的内容非常顺畅:

public class InifiniteTextBlock : Grid
{
    CanvasControl canvasControl;

    public InifiniteTextBlock()
    {
       Initialize();
    }

    private const string loremipsum = @"
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. 
Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. 
Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. 
Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. 
Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, velillum dolore eu feugiat nulla facilisis. ";

    private string largeloremipsum;

    private async void Initialize()
    {
        canvasControl = new CanvasControl() { ClearColor = Colors.Transparent, Width = 480, Height = 4000 };
        largeloremipsum = String.Concat(loremipsum, loremipsum, loremipsum, loremipsum, loremipsum);
        this.Children.Insert(0, canvasControl);
        while (!canvasControl.ReadyToDraw)
        {
            await Task.Delay(60);
        }

        canvasControl.Draw += (s, e) =>
        {
            var test = new CanvasTextFormat();
            e.DrawingSession.DrawText(largeloremipsum, new Rect(0,0,480,4000), Colors.Black, test);
        };
        canvasControl.Invalidate();
    }
}

然后在 XAML 中执行以下操作:
<ScrollViewer>
  <local:InifiniteTextBlock/>
</ScrollViewer>

并且工作得非常好!


文本显示快,但不滚动。所示的代码不起作用。Win2D需要一个NUGET包。喜欢它的速度,可惜它实际上并没有起作用。 - No Refunds No Returns

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接