【发布时间】:2016-07-19 19:47:09
【问题描述】:
我在两个不同的堆栈面板中并排有两个 FlowDocument。我需要一种同时在两个文档中搜索特定文本的方法。就像我在文本框中键入“汽车”一样,流文档阅读器都应该搜索并滚动到“汽车”的下一个实例(如果有的话)。有没有办法实现这一目标? FlowDocument 位于 FlowDocumentReader 中。
【问题讨论】:
标签: c# .net wpf user-interface flowdocument
我在两个不同的堆栈面板中并排有两个 FlowDocument。我需要一种同时在两个文档中搜索特定文本的方法。就像我在文本框中键入“汽车”一样,流文档阅读器都应该搜索并滚动到“汽车”的下一个实例(如果有的话)。有没有办法实现这一目标? FlowDocument 位于 FlowDocumentReader 中。
【问题讨论】:
标签: c# .net wpf user-interface flowdocument
这里我有一个基本的 WPF XAML 布局,其中包含您指定的 2 个 FlowDocumentReader。我有一个搜索文本框,只要搜索文本发生变化,我就会运行后面的代码:
<Window x:Class="WpfFlowTest.MainWindow"
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"
xmlns:local="clr-namespace:WpfFlowTest"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<DockPanel>
<!-- Search Box -->
<TextBox Name="SearchTextBox" DockPanel.Dock="Top" TextChanged="TextBox_TextChanged"/>
<!-- 2 Flow Readers -->
<UniformGrid Columns="2">
<FlowDocumentReader Name="FlowReader1">
<FlowDocument>
<Paragraph>
Here is some text in panel number 1
</Paragraph>
</FlowDocument>
</FlowDocumentReader>
<FlowDocumentReader Name="FlowReader2">
<FlowDocument>
<Paragraph>
Here is some more text in panel number 2
</Paragraph>
</FlowDocument>
</FlowDocumentReader>
</UniformGrid>
</DockPanel>
</Window>
在 MainWindow.xaml.cs 文件中,我有这段代码,它将突出显示文本与您输入的内容匹配的流文档:
private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
var searchText = SearchTextBox.Text;
DoSearch(FlowReader1, searchText);
DoSearch(FlowReader2, searchText);
}
private void DoSearch(FlowDocumentReader reader, string search)
{
var doc = reader.Document;
var text = doc.ContentStart;
var docRange = new TextRange(doc.ContentStart, doc.ContentEnd);
docRange.ClearAllProperties();
while (true)
{
var next = text.GetNextContextPosition(LogicalDirection.Forward);
if (next == null)
{
break;
}
var txt = new TextRange(text, next);
int indx = txt.Text.IndexOf(search);
if (indx > 0)
{
var sta = text.GetPositionAtOffset(indx);
var end = text.GetPositionAtOffset(indx + search.Length);
var textR = new TextRange(sta, end);
// Make it yellow
textR.ApplyPropertyValue(TextElement.BackgroundProperty, new SolidColorBrush(Colors.Yellow));
}
text = next;
}
}
【讨论】:
LineHeight、PagePadding 和任何文档中的其他填充或边距(如段落之间的间距)。
我已经为想要滚动的人发布了我的轻微修改。
private void TextBox_TextChanged(object sender, EventArgs e)
{
var searchText = SearchTextBox.Text;
if (searchText != null || searchText != "")
{
var FlowReader1 = (FlowDocumentReader)diffResults.Children[0];
var FlowReader2 = (FlowDocumentReader)oldResults.Children[0];
DoSearch(FlowReader1, searchText);
DoSearch(FlowReader2, searchText);
}
}
private void DoSearch(FlowDocumentReader reader, string search)
{
bool toScroll = true;
var doc = reader.Document;
var text = doc.ContentStart;
var docRange = new TextRange(doc.ContentStart, doc.ContentEnd);
docRange.ClearAllProperties();
while (true)
{
var next = text.GetNextContextPosition(LogicalDirection.Forward);
if (next == null)
{
break;
}
var txt = new TextRange(text, next);
int indx = txt.Text.IndexOf(search);
if (indx >= 0)
{
var sta = text.GetPositionAtOffset(indx);
var end = text.GetPositionAtOffset(indx + search.Length);
if (end == null)
{
end = text.GetPositionAtOffset(indx + 1);
}
var textR = new TextRange(sta, end);
if (toScroll && text.Paragraph != null)
{
text.Paragraph.BringIntoView();
toScroll = false;
}
// Make it yellow
textR.ApplyPropertyValue(TextElement.BackgroundProperty, new SolidColorBrush(Colors.Yellow));
}
text = next;
}
【讨论】:
BringIntoView() 确实将它带入了Viewport,但它并不一定将它带到Viewport 中的任何预设位置,我猜这就是您要找的,抱歉.我只是假设你想要它在Viewport 的顶部,所以那是我的错。但是如果你想把文本放在它的最顶端,除非有什么我不知道的,你实际上必须计算它。这就是我必须做的。