Подход в этой статье у меня работал:
WPF RichTextBox не обеспечивает функциональность для регулировки его ширины
к тексту. Насколько я знаю, RichTextBox использует FlowDocumentView в
его визуальное дерево для визуализации Flowdocument. Это займет доступное
пространство для отображения его содержимого, поэтому он не будет регулировать его размер
содержание. Поскольку это внутренний класс, кажется, мы не можем переопределить
процесс макета, чтобы RichTextBox мог регулировать свой размер в соответствии с
текст.
Поэтому я думаю, что ваш подход в правильном направлении.
К сожалению, исходя из моих исследований, нет прямого пути
измерить размер отображаемого текста в RichTextBox.
Есть обходной путь, который мы можем попробовать. Мы можем перебрать поток документов
в RichTextBox рекурсивно для извлечения всех объектов Run и Paragraph.
Затем мы конвертируем их в FormattedText, чтобы получить размер.
В этой статье показано, как преобразовать FlowDocument в
FormattedText. Я также пишу простой пример, используя
Класс FlowDocumentExtensions в этой статье.
public Window2()
{
InitializeComponent();
StackPanel layoutRoot = new StackPanel();
RichTextBox myRichTextBox = new RichTextBox() { Width=20};
this.Content = layoutRoot;
layoutRoot.Children.Add(myRichTextBox);
myRichTextBox.Focus();
myRichTextBox.TextChanged += new TextChangedEventHandler((o,e)=>myRichTextBox.Width=myRichTextBox.Document.GetFormattedText().WidthIncludingTrailingWhitespace+20);
}
public static class FlowDocumentExtensions
{
private static IEnumerable<TextElement> GetRunsAndParagraphs(FlowDocument doc)
{
for (TextPointer position = doc.ContentStart;
position != null && position.CompareTo(doc.ContentEnd) <= 0;
position = position.GetNextContextPosition(LogicalDirection.Forward))
{
if (position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.ElementEnd)
{
Run run = position.Parent as Run;
if (run != null)
{
yield return run;
}
else
{
Paragraph para = position.Parent as Paragraph;
if (para != null)
{
yield return para;
}
}
}
}
}
public static FormattedText GetFormattedText(this FlowDocument doc)
{
if (doc == null)
{
throw new ArgumentNullException("doc");
}
FormattedText output = new FormattedText(
GetText(doc),
CultureInfo.CurrentCulture,
doc.FlowDirection,
new Typeface(doc.FontFamily, doc.FontStyle, doc.FontWeight, doc.FontStretch),
doc.FontSize,
doc.Foreground);
int offset = 0;
foreach (TextElement el in GetRunsAndParagraphs(doc))
{
Run run = el as Run;
if (run != null)
{
int count = run.Text.Length;
output.SetFontFamily(run.FontFamily, offset, count);
output.SetFontStyle(run.FontStyle, offset, count);
output.SetFontWeight(run.FontWeight, offset, count);
output.SetFontSize(run.FontSize, offset, count);
output.SetForegroundBrush(run.Foreground, offset, count);
output.SetFontStretch(run.FontStretch, offset, count);
output.SetTextDecorations(run.TextDecorations, offset, count);
offset += count;
}
else
{
offset += Environment.NewLine.Length;
}
}
return output;
}
private static string GetText(FlowDocument doc)
{
StringBuilder sb = new StringBuilder();
foreach (TextElement el in GetRunsAndParagraphs(doc))
{
Run run = el as Run;
sb.Append(run == null ? Environment.NewLine : run.Text);
}
return sb.ToString();
}
}