Вам нужно разделить ваш Run
, если вы хотите выделить какой-то текст в середине этого Run
.Поэтому замена текста поиска на пустую строку не будет работать.
Ваша исходная структура текста выглядит следующим образом:
<Run>
<Text>
I am going to school
</Text>
</Run>
Если вы хотите выделить слово going
, вам нужносделайте из него более сложную структуру:
<Run>
<Text>
I am
</Text>
</Run>
<Run>
<Text>
going
</Text>
</Run>
<Run>
<Text>
to school
</Text>
</Run>
Затем можно выделить Run
в середине для выделения.
Вот пример рабочего кода.Обратите внимание, в этом коде нет ошибок при передаче !Это должно дать вам представление о том, как решить вашу задачу.Реализуйте правильную обработку исключений для производственного использования!
Также обратите внимание, что этот пример ищет только первое вхождение, как в вашем коде.Если вам нужно выделить несколько поисковых запросов, вам нужно будет улучшить этот код.
void HighLightText(Paragraph paragraph, string text)
{
// Search for a first occurrence of the text in the text runs
var found = paragraph
.Descendants<Run>()
.Where(r => !string.IsNullOrEmpty(r.InnerText) && r.InnerText != "\\s")
.Select(r =>
{
var runText = r.GetFirstChild<Text>();
int index = runText.Text.IndexOf(text, StringComparison.OrdinalIgnoreCase);
// 'Run' is a reference to the text run we found,
// TextNode is a reference to the run's Text object,
// 'TokenIndex` is the index of the search string in run's text
return new { Run = r, TextNode = runText, TokenIndex = index };
})
.FirstOrDefault(o => o.TokenIndex >= 0);
// Nothing found -- escape
if (found == null)
{
return;
}
// Create a node for highlighted text as a clone (to preserve formatting etc)
var highlightRun = found.Run.CloneNode(true);
// Add the highlight node after the found text run and set up the highlighting
paragraph.InsertAfter(highlightRun, found.Run);
highlightRun.GetFirstChild<Text>().Text = text;
RunProperties runPro = new RunProperties();
Highlight highlight = new Highlight { Val = HighlightColorValues.Yellow };
runPro.AppendChild(highlight);
highlightRun.InsertAt(runPro, 0);
// Check if there's some text in the text run *after* the found text
int remainderLength = found.TextNode.Text.Length - found.TokenIndex - text.Length;
if (remainderLength > 0)
{
// There is some text after the highlighted section --
// insert it in a separate text run after the highlighted text run
var remainderRun = found.Run.CloneNode(true);
paragraph.InsertAfter(remainderRun, highlightRun);
var textNode = remainderRun.GetFirstChild<Text>();
textNode.Text = found.TextNode.Text.Substring(found.TokenIndex + text.Length);
// We need to set up this to preserve the spaces between text runs
textNode.Space = new EnumValue<SpaceProcessingModeValues>(SpaceProcessingModeValues.Preserve);
}
// Check if there's some text *before* the found text
if (found.TokenIndex > 0)
{
// Something is left before the highlighted text,
// so make the original text run contain only that portion
found.TextNode.Text = found.TextNode.Text.Remove(found.TokenIndex);
// We need to set up this to preserve the spaces between text runs
found.TextNode.Space = new EnumValue<SpaceProcessingModeValues>(SpaceProcessingModeValues.Preserve);
}
else
{
// There's nothing before the highlighted text -- remove the unneeded text run
paragraph.RemoveChild(found.Run);
}
}
Этот код работает для выделения слов I
, going
или school
в I am going to school
предложение.