WPF: get wrapped text from text field

Is there a way in WPF to get text formatted as it appears in the text box when TextWrapping = "Wrap"?

<TextBox Width="200" TextWrapping="Wrap" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto" /> 

I tried to use the TextFormatter class, but it allows me to draw text in the drawing context, where I only need text with line break enabled.

+5
source share
4 answers

Here's how to get the full text with obvious line breaks.

Note:

  • Include the following classes from the Advanced text formatting format in your project:
    • CustomTextSource
    • Fontrendering
    • GenericTextProperties
  • There are some limitations mentioned in the CustomTextSource class. However, I believe that your requirements are not affected by these restrictions.
  • These are just examples. You can change the code to suit your needs.
  • The code still uses a hack (albeit a decent one) - InputTextBox.ViewportWidth . You might want to check if the end result is what you want.

See: Advanced Text Formatting and Text Formatting Example

Code example
XAML:

 <Window x:Class="TextFormatterForWrappedText.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525"> <Grid> <TextBox Width="200" x:Name="InputTextBox" TextWrapping="Wrap" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto" Margin="23,12,280,241" /> <TextBox x:Name="FormattedDisplayTextBox" Height="172" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="23,105,0,0" Width="438" AcceptsReturn="True" TextWrapping="Wrap" /> <Button HorizontalAlignment="Left" VerticalAlignment="Top" Margin="257,12,0,0" Height="23" Content="Copy" Name="CopyButton" Width="129" Click="CopyButton_Click" /> </Grid> </Window> 

Codebehind:

 private void CopyButton_Click(object sender, RoutedEventArgs e) { List<string> stringList = GetTextAsStringList(); StringBuilder sb = new StringBuilder(); foreach (string s in stringList) { sb.Append(s); sb.Append("\r\n"); } Clipboard.SetData(System.Windows.DataFormats.Text, sb.ToString()); FormattedDisplayTextBox.Clear(); FormattedDisplayTextBox.Text = sb.ToString(); } private List<string> GetTextAsStringList() { List<string> stringList = new List<string>(); int pos = 0; string inputText = InputTextBox.Text; CustomTextSource store = new CustomTextSource(); store.Text = inputText; store.FontRendering = new FontRendering(InputTextBox.FontSize, InputTextBox.TextAlignment, null, InputTextBox.Foreground, new Typeface(InputTextBox.FontFamily, InputTextBox.FontStyle, InputTextBox.FontWeight, InputTextBox.FontStretch)); using (TextFormatter formatter = TextFormatter.Create()) { while (pos < store.Text.Length) { using (TextLine line = formatter.FormatLine(store, pos, InputTextBox.ViewportWidth, new GenericTextParagraphProperties( store.FontRendering), null)) { stringList.Add(inputText.Substring(pos, line.Length - 1)); pos += line.Length; } } } return stringList; } 
+3
source

To do this, you need to write your own logic using the text dimension API.

STEP 1: Bresk text text box for words.

STEP 2: Then measure the width of each word and combine them until the line width is less than the width of the text box.

Refer to this post, which explains the process of measuring text. (Social.msdn.microsoft.com/forums/en-US/wpf/thread / ...)

+1
source

See Ian Griffiths answer to this question: Get display text from TextBlock

It displays the text (as shown on the screen) with a TextBlock , but I think you can also use it for a TextBox as well

+1
source

If all you need is the text of the text field (full text, not just the visible part), which will be displayed as text (with apparent line breaks) in the same window in some text block, a quick hack could be:

 FormattedText ft = new FormattedText(textBox1.Text, System.Globalization.CultureInfo.CurrentCulture, textBox1.FlowDirection, new Typeface(textBox1.FontFamily, textBox1.FontStyle, textBox1.FontWeight, textBox1.FontStretch), textBox1.FontSize, textBox1.Foreground); ft.TextAlignment = textBox1.TextAlignment; ft.Trimming = TextTrimming.None; ft.MaxTextWidth = textBox1.ViewportWidth; textBlock1.Width = textBox1.ViewportWidth; textBlock1.Height = ft.Height; textBlock1.TextAlignment = textBox1.TextAlignment; textBlock1.TextWrapping = textBox1.TextWrapping; textBlock1.Text = textBox1.Text; 

If necessary in some other place, you can transfer values ​​to this place and use them in a text block.

If you need the full text (with apparent line breaks) in the form of a list of lines (for example, List<string> ), where each element represents a visible line, you will need a comprehensive solution.
Also, if you only need the visible part of the text displayed in the text box, again some complex solution is required.

+1
source

All Articles