В RichTextBox неправильно выделяются символы
Если просто запустить простой пример кода то первые нажатия на кнопку не принесут эффекта В TextRange.Text будет "". И даже если ставить проверку что бы оно пропускало данные случаи, то все равно не будет работать. Так как же мне выделить и поменять текст?
<Grid>
<RichTextBox x:Name="TextField" HorizontalAlignment="Left" Height="180" Margin="258,43,0,0" VerticalAlignment="Top" Width="316">
<FlowDocument>
<Paragraph>
<Run Text="RichTextBox"/>
</Paragraph>
</FlowDocument>
</RichTextBox>
<Button Content="Click" HorizontalAlignment="Left" Height="44" Margin="258,268,0,0" VerticalAlignment="Top" Width="316" Click="Button_Click"/>
</Grid>
int i = 0;
public MainWindow()
{
InitializeComponent();
string text = "aaaaa";
TextField.IsReadOnly = true;
TextField.Document.Blocks.Clear();
TextField.Document.Blocks.Add(new Paragraph(new Run(text)));
}
private void Button_Click(object sender, RoutedEventArgs e)
{
TextRange rangeForLetter = new
TextRange(TextField.Document.ContentStart.GetPositionAtOffset(i),
TextField.Document.ContentStart.GetPositionAtOffset(i + 1));
rangeForLetter.ApplyPropertyValue(TextElement.ForegroundProperty, Brushes.Red);
i++;
}
Ответы (1 шт):
Например, можно сделать так:
XAML
<Window x:Class="TestApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Test" Height="200" Width="400">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<RichTextBox x:Name="TextField" IsReadOnly="True" Grid.Row="0">
<FlowDocument>
<Paragraph Margin="0">
<Run Text="hello world"/>
</Paragraph>
<Paragraph Margin="0">
<Run Text="goodbye world"/>
</Paragraph>
</FlowDocument>
</RichTextBox>
<Button Content="Next" HorizontalAlignment="Center" Click="PaintNext"
Grid.Row="1" Margin="5" MinWidth="75" x:Name="NextButton"/>
</Grid>
</Window>
Code-behind:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
curr = FindNextSymbol(TextField.Document.ContentStart);
NextButton.IsEnabled = curr != null;
}
TextRange curr;
TextRange FindNextSymbol(TextPointer from)
{
while (true)
{
var ctx = from.GetPointerContext(LogicalDirection.Forward);
if (ctx == TextPointerContext.None)
return null;
var next = from.GetPositionAtOffset(1, LogicalDirection.Forward);
if (ctx == TextPointerContext.Text)
return new TextRange(from, next);
from = next;
}
}
void PaintNext(object sender, RoutedEventArgs e)
{
if (curr == null)
return;
curr.ApplyPropertyValue(TextElement.BackgroundProperty, Brushes.Red);
curr = FindNextSymbol(curr.End);
if (curr == null)
NextButton.IsEnabled = false;
}
}
Результат:
Объяснение: Позиции в RichTextBox не обязательно соответствуют границам букв. Всякие невидимые элементы наподобие начала/конца абзацев тоже являются позицией. Для того, чтобы найти позицию текста, мы идём по одному шагу от начала документа вправо, и проверяем тип содержимого справа от текущей позиции. Как только находим текстовый тип, окрашиваем его в нужный цвет.
Обратите внимание на две вещи. Во-первых, код, который я привёл, не следует принципам MVVM (потому, что он занимается чисто визуальной логикой). Затем, я перерисовал ваш UI с использованием layout manager'а, так должно работать с разными размерами окна.
