Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/313.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用WPF显示流式富文本_C#_.net_Wpf_Flowdocument - Fatal编程技术网

C# 使用WPF显示流式富文本

C# 使用WPF显示流式富文本,c#,.net,wpf,flowdocument,C#,.net,Wpf,Flowdocument,我有一个WPF应用程序,它通过一个套接字连接到一个设备,并获取流式文本数据(大约每秒1条消息)。然后,该数据将显示在UI上。用户可以创建规则,如“如果数据包含'abc'突出显示行”或“…使其加粗”,因此纯文本输出将不起作用,它需要是“富”文本 我目前的解决方案是在我的ViewModel中有一个包含格式化输出的。该视图具有绑定到ViewModel中的FlowDocument的 这是可行的,但当FlowDocument变大(约6000行)时,性能开始下降。目前的算法将行数限制在10000行,但情况变

我有一个WPF应用程序,它通过一个套接字连接到一个设备,并获取流式文本数据(大约每秒1条消息)。然后,该数据将显示在UI上。用户可以创建规则,如“如果数据包含'abc'突出显示行”或“…使其加粗”,因此纯文本输出将不起作用,它需要是“富”文本

我目前的解决方案是在我的ViewModel中有一个包含格式化输出的。该视图具有绑定到ViewModel中的FlowDocument的

这是可行的,但当FlowDocument变大(约6000行)时,性能开始下降。目前的算法将行数限制在10000行,但情况变得更糟,应用程序无法使用。当它达到10000行时,我会为添加的每一行删除一行,从而使FlowDocumentScrollViewer为每一新行获得2个更新通知

我试图找到一种批量删除的方法(当我们达到10000行时,删除最旧的1000行),但是在FlowDocument上没有批量删除。循环1000次并执行删除操作将导致1000次更新通知并锁定UI

这是我的问题,我的问题是:

使用WPF显示流式富文本内容的最佳方式是什么?我每秒收到约1条消息,每条消息约150个字符,我想保留最后10000条消息。我走错方向了吗?是否有其他性能更好的控件/对象

编辑:这里还有一些要求

  • 需要能够打印输出文本
  • 需要能够选择并复制输出文本,以便将其粘贴到另一个文档中

由于能够在列中显示内容等,FlowDocumentScrollViewer可能会有开销。是否有原因导致普通WPF RichTextBox无法工作?另外,您有.NET3.5SP1吗?下面的链接表明,SP1中的FlowDocuments有了很大的性能改进:。

这个想法使事情变得非常复杂,但我的想法是为每条消息创建一个查看器,并且只创建显示当前可见消息所需的查看器。我认为VirtualzingStackPanel控件将是一个很好的管理工具。我发现了一个描述虚拟化面板实现的系列

显然,这意味着在单独的数据结构中维护消息缓冲区

编辑:我刚刚意识到标准ListBox控件在其实现中使用了VirtualzingStackPanel。有鉴于此,我的修订建议是:

  • 创建包含每条消息源的数据结构
  • 在数据结构上创建一个属性,该属性从消息源“动态”创建FlowDocument
  • 将列表框绑定到所述数据结构的集合
  • 使用FlowDocumentScrollViewer为列表框定义ItemTemplate,其中文档属性绑定到上述数据结构的属性
  • 编辑2:关于打印/缩放:我无法在WPF中帮助您进行打印(可能涉及VisualBrush?),但缩放应该很容易做到。我创建了一个中联重科盒子来测试这个想法。XAML如下所示:

    <ListBox
        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"
        x:Class="Test.ZoomListBox"
        d:DesignWidth="640" d:DesignHeight="480"
        x:Name="ThisControl">
        <ListBox.ItemsPanel>
            <ItemsPanelTemplate>
                <VirtualizingStackPanel IsItemsHost="True">
                    <VirtualizingStackPanel.LayoutTransform>
                        <ScaleTransform ScaleX="{Binding ElementName=ThisControl, Path=Zoom}" ScaleY="{Binding ElementName=ThisControl, Path=Zoom}" />
                    </VirtualizingStackPanel.LayoutTransform>
                </VirtualizingStackPanel>
            </ItemsPanelTemplate>
        </ListBox.ItemsPanel>
    </ListBox>
    
    以及一个使用它的示例:

    <Grid x:Name="LayoutRoot">
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <l:ZoomListBox x:Name="ZoomList">
            <Button>Foo</Button>
            <Button>Foo</Button>
            <Button>Foo</Button>
            <Button>Foo</Button>
            <Button>Foo</Button>
            <Button>Foo</Button>
            <Button>Foo</Button>
        </l:ZoomListBox>
        <Slider Grid.Row="1" Value="{Binding ElementName=ZoomList, Path=Zoom}" Minimum="0.5" Maximum="5" /> 
    </Grid>
    
    
    福
    福
    福
    福
    福
    福
    福
    
    性能崩溃似乎是由FlowDocument中的大量块造成的。对于收到的每一条消息,我都在创建一个运行,将该运行添加到一个段落,并将该段落添加到文档中

    我改变了算法,所以现在它创建了一个段落,然后在该段落中添加250次,然后创建一个新段落。。。添加250次运行。。。等等这实际上将块的数量减少了一半

    当我达到最大行数(10000)时,这还有一个额外的好处。我可以删除最旧的段落,而不是为每增加一行删除一行(并固定CPU),这会立即删除最旧的250行


    这一相对简单的改变使性能在可接受的范围内。不再固定CPU和锁定UI,现在CPU保持相对较低,峰值约为15%。

    它最初是一个RichTextBox,但我将其更改为打印、缩放。。。免费的。根据我所做的测试,大约一半的性能影响来自FlowDocumentScrollViewer,另一半来自FlowDocument本身?另外,有关进一步的文本优化技巧,请参阅。有趣的想法,感谢您“跳出框框”。我将研究类似的内容,但我需要能够从输出区域选择/复制数据。另外,我现在可以免费打印和缩放,所以我需要想出一个解决方案。我可以在我的机器上使用类似的场景,而不会出现显著的性能问题(例如,它将数据作为字符串。我创建一个带有字符串的运行,然后创建一个带有运行的段落。然后我将其命名为.MyFlowDoc.Blocks.Add)(第段);
    <Grid x:Name="LayoutRoot">
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <l:ZoomListBox x:Name="ZoomList">
            <Button>Foo</Button>
            <Button>Foo</Button>
            <Button>Foo</Button>
            <Button>Foo</Button>
            <Button>Foo</Button>
            <Button>Foo</Button>
            <Button>Foo</Button>
        </l:ZoomListBox>
        <Slider Grid.Row="1" Value="{Binding ElementName=ZoomList, Path=Zoom}" Minimum="0.5" Maximum="5" /> 
    </Grid>