我有一些小应用程序可以读取一个非常大的文件。为了显示这个文件(可以有大约百万行),我使用 virtualizedStackpanel 和滚动视图来虚拟化 UI。
在这个文件中,我实现了类似搜索的功能,它突出显示包含搜索字符串的行。每行由文本块表示。
所以我有我的集合绑定到的 ItemsControl。作为项目数据模板,我有 contentControl(带有高亮转换器,因此行会改变颜色)并且 ItemsPanelTemplate 是 VirtualizingStackPanel 和 ItemsControl 的 ControlTemplate 是带有嵌套 ItemsPresenter 的 ScrollViewer
<ItemsControl Grid.Row="2" ItemsSource="{Binding FileContent}"
ScrollViewer.CanContentScroll="True"
VirtualizingStackPanel.IsVirtualizing="True"
VirtualizingStackPanel.VirtualizationMode="Recycling">
<ItemsControl.ItemTemplate>
<DataTemplate>
<ContentControl Content="{Binding Text, Converter={StaticResource HighlightConverter}}">
</ContentControl>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.Template>
<ControlTemplate>
<ScrollViewer >
<ItemsPresenter/>
</ScrollViewer>
</ControlTemplate>
</ItemsControl.Template>
</ItemsControl>
在后台代码(ViewModel)中,我有一个接受字符串的函数,并在包含所有行的 ObservableCollection 中搜索这个字符串(并且文本块由每一行组成)。和两种搜索方法。第一种方法在集合中查找结果并将特殊字符插入到 TextBlock 文本中,以便可以应用突出显示。(以及从先前搜索中删除突出显示的文本的第二个功能)
private void SearchText()
{
this.RemovePreviousSearchResults();
searchResults = new ObservableCollection<RowModel>(this.FileContent.Where(x => x.Text.Contains(this.TextToFind)));
foreach (RowModel row in searchResults)
{
row.UpdateTextWithNotify("|~S~|" + row.Text + "|~E~|");
}
}
private void RemovePreviousSearchResults()
{
if (this.searchResults.Count > 0)
{
foreach (RowModel row in searchResults)
{
row.UpdateTextWithNotify(row.Text.Replace("|~S~|", "").Replace("|~E~|", ""));
}
}
}
现在我想有一些能力将滚动视图集中到找到的结果上。当您在文本编辑器中按 CTRL + F 然后单击“查找下一个”时,类似的东西。
但我不知道如何在不破坏 MVVM 规则的情况下实现这一点。我想过在文本块中添加更多的控制字符串/字符和结果,但是我怎样才能强制滚动视图滚动到它们上呢?
如果没有像 ListView 这样的东西,这甚至可能吗?