这个想法使事情变得非常复杂,但我的想法是为每条消息创建一个查看器,并且只创建显示当前可见消息所需的数量的查看器。我认为 VirtualizingStackPanel 控件将是一个很好的工具来管理它。我在这里找到了一个描述 VirtualizingStackPanel 实现的系列。
显然,这意味着在单独的数据结构中维护消息缓冲区。
编辑:我刚刚意识到标准 ListBox 控件在其实现中使用了 VirtualizingStackPanel。考虑到这一点,我修改后的建议是:
- 创建一个数据结构来包含每条消息的来源。
- 在数据结构上创建一个属性,该属性“动态”从消息源创建 FlowDocument
- 将 ListBox 绑定到所述数据结构的集合。
- 使用 FlowDocumentScrollViewer 为 ListBox 定义 ItemTemplate,其中 Document 属性绑定到上述数据结构的属性。
编辑 2:关于打印/缩放:我无法帮助您在 WPF 中打印(可能涉及 VisualBrush 的东西?),但缩放应该很容易做到。我创建了一个 ZoomListBox 来测试这个想法。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>
后面的代码是这样的:
public partial class ZoomListBox
{
public ZoomListBox()
{
this.InitializeComponent();
}
public double Zoom
{
get { return (double)GetValue(ZoomProperty); }
set { SetValue(ZoomProperty, value); }
}
// Using a DependencyProperty as the backing store for Zoom. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ZoomProperty =
DependencyProperty.Register("Zoom", typeof(double), typeof(ZoomListBox), new UIPropertyMetadata(1.0));
}
以及一个使用它的例子:
<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>