我有一些小应用程序,它读取一个非常大的文件。为了显示这个文件(可以有大约数百万行)我使用virtualizedStackpanel和scrollview来虚拟化UI。
在这个文件中我实现了类似搜索的内容,它突出显示包含搜索字符串的行。每行由textblock表示。
所以我有ItemsControl我绑定我的集合。作为项目datatemplate我有contentControl(使用高亮转换器,因此行将更改颜色)和ItemsPanelTemplate是VirtualizingStackPanel和ItemsControl的ControlTemplate是ScrollViewer与嵌套ItemsPresenter
<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~|", ""));
}
}
}
现在我有能力将scrollview集中到找到的结果。在文本编辑器中按CTRL + F,然后单击“查找下一个”。
但我不知道如何在不违反MVVM规则的情况下实现这一点。我想在文本块中添加更多控制字符串/字符和结果,但是我如何强制滚动视图滚动到它们上?
如果没有像ListView这样的东西,这是否可行?
答案 0 :(得分:1)
看起来你正试图在这里重新发明轮子,为什么不使用一些可用的控件,如
https://github.com/keyoti/RapidFindReplaceWPF
https://www.codeproject.com/Articles/173509/A-Universal-WPF-Find-Replace-Dialog