我正在尝试将插入符号放在Run中的RichTextBox中,使用户能够继续使用相同的格式进行输入。在此运行之后,还有另一个具有不同格式的运行。
以下是一些代码,向您展示我的意思:
private void Button_Click(object sender, RoutedEventArgs e)
{
Paragraph p = new Paragraph();
// Add the new Paragraph to the RichTextBox flowdocument.
rtb1.Document.Blocks.Add(p);
// Create the first Run.
Run r1 = new Run("This is a ");
// Create the second Run.
Run r2 = new Run("test");
r2.TextDecorations = TextDecorations.Underline;
// Add the new Runs to the Paragraph.
p.Inlines.Add(r1);
p.Inlines.Add(r2);
// Place the caret at the end of the first Run, and give focus to the RichTextBox.
rtb1.CaretPosition = r1.ContentEnd;
rtb1.Focus();
}
如果我继续输入,新输入将获得与第二次运行相同的格式。
我也尝试将CaretPosition设置为
new TextRange(r1.ElementEnd, r1.ElementEnd).Start
希望由于它将逻辑方向设置为向后,它可以工作,但无济于事。
有没有办法在第一次运行中设置CaretPosition?
答案 0 :(得分:1)
我观察了当我选择“a”和“test”之间的空格并开始输入时发生的事情,并看到创建了一个新的Run。我尝试创建一个新的Run并将它放在r1和r2之间,并将CaretPosition设置为newRun.ContentStart,但这不起作用。
我发现如果我...
...我可以使用与新Run相同的格式继续输入。
我不喜欢这种方法,因为我需要创建一个新的Run而不是只使用它前面的那个。我会留在这里以防万一没有人知道更好的方法,如果没有人能提供更好的解决方案,我会在一周内接受它作为最佳答案。
以下是完整的代码:
private void Button_Click(object sender, RoutedEventArgs e)
{
Paragraph p = new Paragraph();
// Add the new Paragraph to the RichTextBox flowdocument.
rtb1.Document.Blocks.Add(p);
// Create the first Run.
Run r1 = new Run("This is a ");
// Create the second Run.
Run r2 = new Run("test");
r2.TextDecorations = TextDecorations.Underline;
// Add the new Runs to the Paragraph.
p.Inlines.Add(r1);
p.Inlines.Add(r2);
// Create a new Run. This will be placed between r1 and r2.
Run newRun = new Run();
// Copy the formatting from r1 to our new Run.
CopyInlineFormattingToRun(r1, ref newRun);
// Set the text of the new Run to be a space.
newRun.Text = " ";
// Place our new Run after r1.
CreateNewRunAfterExistingRun(r1, newRun);
// Put the caret at the start of newRun.
rtb1.CaretPosition = newRun.ContentStart;
// Remove the space at the end of newRun.
newRun.ContentEnd.DeleteTextInRun(-1);
// Give focus to the RichTextBox.
rtb1.Focus();
}
/// <summary>
/// Copies some of the properties in <paramref name="mainInline"/> to <paramref name="receiverRun"/>.
/// </summary>
/// <param name="mainInline">The <see cref="Inline"/> containing the desired formatting.</param>
/// <param name="receiverRun">The <see cref="Run"/> which should receive the formattinh from <paramref name="mainInline"/>.</param>
internal static void CopyInlineFormattingToRun(Inline mainInline, ref Run receiverRun)
{
receiverRun.FontFamily = mainInline.FontFamily;
receiverRun.FontSize = mainInline.FontSize;
receiverRun.FontStretch = mainInline.FontStretch;
receiverRun.FontStyle = mainInline.FontStyle;
receiverRun.FontWeight = mainInline.FontWeight;
receiverRun.Foreground = mainInline.Foreground;
receiverRun.Background = mainInline.Background;
receiverRun.TextDecorations = mainInline.TextDecorations;
}
/// <summary>
/// Places a <see cref="Run"/> after an existing <see cref="Run"/>.
/// </summary>
/// <param name="existingRun">The existing <see cref="Run"/> already present in the <see cref="FlowDocument"/>.</param>
/// <param name="newRun">The new <see cref="Run"/> which will be placed after the <paramref name="existingRun"/> in the <see cref="FlowDocument"/>.</param>
private void CreateNewRunAfterExistingRun(Run existingRun, Run newRun)
{
Paragraph p = (Paragraph)existingRun.Parent;
p.Inlines.InsertAfter(existingRun, newRun);
}
如果您想在Run的另一侧执行此操作,则需要更改CreateNewRunAfterExistingRun()以使用InsertAfter而不是ContentStart,您将不得不使用
// Put the caret at the start of newRun.
rtb1.CaretPosition = newRun.ContentEnd;
编辑: 您可以订阅 LostFocus 或 LostKeyboardFocus 事件,并根据需要合并两个运行。
答案 1 :(得分:0)
诀窍在于运行有两个“结束”点。
而不是rtb1.CaretPosition = newRun.ContentEnd;
(似乎只是在运行结束时“外面”),使用rtb1.CaretPosition = newRun.ElementEnd;
(这似乎只是“在其中”)然后是任何活动的风格运行结束将应用于随后键入的所有文本。
通过对已接受答案的调整,无需添加空格,然后DeleteTextInRun(-1)
来诱使控件正常工作。