#c# #winforms #richtextbox #highlight
#c# #winforms #richtextbox #выделить
Вопрос:
Я пытаюсь выделить несколько строк определенного текста в RichTextBox.
Вот мой код для выделения текста:
public void HighlightMistakes(RichTextBox richTextBox)
{
string[] phrases = { "Drivers Do Not Match", "Current Does Not Match", "No Drivers Found" };
foreach (var phrase in phrases)
{
int startIndex = 0;
while (startIndex <= richTextBox.TextLength)
{
int phraseStartIndex = richTextBox.Find(phrase, startIndex, RichTextBoxFinds.None);
if (phraseStartIndex != -1)
{
richTextBox.SelectionStart = phraseStartIndex;
richTextBox.SelectionLength = phrase.Length;
richTextBox.SelectionBackColor = Color.Yellow;
}
else break;
startIndex = phraseStartIndex phrase.Length;
}
}
}
Вот как я добавляю текст в RTB и вызываю функцию выше:
foreach (var a in resultList)
{
richTextBox1.AppendText("n" a "n");
HighlightMistakes(richTextBox1);
}
Однако HighlightMistakes
работает не так, как мне бы хотелось. Идея состоит в том, чтобы выделить все строковые значения, указанные в phrases
массиве, и это происходит не каждый раз.
Примеры:
Я не уверен, почему некоторые строки пропущены, а некоторые нет.
Комментарии:
1. Вы пробовали отладчик , вашего самого лучшего друга в мире кодирования.
2. Подумайте: у вас есть
SelectionStart = phraseStartIndex
— это означаетphraseStartIndex
, что включает расстояние от начала текста и уже учитываетstartIndex
значение. Затем вы добавляетеphraseStartIndex
вstartIndex
, что означает, что вы устанавливаетеstartIndex
значениеstartIndex startIndex phraseOffset phrase.Length
, чтобы пропустить текст. Не добавлять, устанавливатьstartIndex = phraseStartIndex phrase.Length
3. @NetMage, спасибо за предложение, но если я это сделаю, программа зависнет, и приложение перейдет в режим перерыва:(
4. @NetMage однако, когда я удаляю
phraseStartIndex
из уравнения, повторяющиеся строки больше не пропускаются. Спасибо за подсказку. Теперь у меня естьstartIndex = phrase.Length
5. Я не думаю, что это правильно — вероятно, он помечает фразы несколько раз. Вы уверены, что пробовали
startIndex = phraseStartIndex phrase.Length;
? Моя тестовая программа отлично работает, когда я делаю это с вашими примерами.
Ответ №1:
Если вы ничего не имеете против простого метода регулярных выражений, вы можете использовать Regex.Совпадения для сопоставления вашего списка фраз с текстом вашего RichTextBox.
Каждое совпадение в коллекции совпадений содержит как индекс (позицию внутри текста), где найдено совпадение, так и его длину, поэтому вы можете просто вызвать .Выберите (индекс, длина), чтобы выбрать фразу и выделить ее.
Используемый шаблон представляет собой строку, полученную в результате объединения фраз для сопоставления с каналом ( |
).
Каждая фраза передается в Regex.Escape(), поскольку текст может содержать метасимволы.
Если вы хотите рассмотреть этот случай, удалите RegexOptions.IgnoreCase
.
using System.Text.RegularExpressions;
string[] phrases = { "Drivers Do Not Match",
"Current Does Not Match",
"No Drivers Found" };
HighlightMistakes(richTextBox1, phrases);
private void HighlightMistakes(RichTextBox rtb, string[] phrases)
{
ClearMistakes(rtb);
string pattern = string.Join("|", phrases.Select(phr => Regex.Escape(phr)));
var matches = Regex.Matches(rtb.Text, pattern, RegexOptions.IgnoreCase);
foreach (Match m in matches) {
rtb.Select(m.Index, m.Length);
rtb.SelectionBackColor = Color.Yellow;
}
}
private void ClearMistakes(RichTextBox rtb)
{
int selStart = rtb.SelectionStart;
rtb.SelectAll();
rtb.SelectionBackColor = rtb.BackColor;
rtb.SelectionStart = selStart;
rtb.SelectionLength = 0;
}