I have some small app which reads a very large file. In order to display this file (can have about milion rows) im using virtualizedStackpanel and scrollview to virtualize UI.
In this file i implemented something like searching, which highlights rows which contains searched string. Each row is represented by textblock.
So i have ItemsControl to which i bind my collection. As item datatemplate i have contentControl (with highlight converter, so row will change color) and ItemsPanelTemplate is VirtualizingStackPanel and ControlTemplate of ItemsControl is ScrollViewer with nested 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>
In background code (ViewModel) i have function which accepts string and search this string in ObservableCollection which contains all rows (and textblocks are made from each row). And two methods for searching. First method finds results in collection and insert special characters into TextBlock text so highlighting can be applied. (and second fucntion which removes highlighted text from previous search)
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~|", ""));
}
}
}
And now i wana to have some ability to focus scrollview to found results. Something similar when you press CTRL + F in text editor and then click on Find Next.
But i have no idea how to implemet this without breaking MVVM rules. I thought about adding some more control string/character into textblock with results but how can i force scrollview to scroll onto them?
Is this even posible without something like ListView?
It seems like you're trying to re-invent the wheel here, Why don't you use some of the available controls like
https://github.com/keyoti/RapidFindReplaceWPF
https://www.codeproject.com/Articles/173509/A-Universal-WPF-Find-Replace-Dialog