Is there a way in WPF to get the text formatted as it display on the textbox when TextWrapping=\"Wrap\"?
If all you want is the text of textbox (complete text and not just the visible part), to be displayed as text (with apparent line breaks) on the same window in some textblock, 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 its required in some other place, you can carry the values to that place and use them on the textblock there.
If you need the complete text (with apparent line breaks) as a list of string (e.g. List<string>
) where each item represents the apparent line, you will need a complex solution.
Also, if you need only the visible part of text as displayed in the textbox, again some complex solution is required.
Here's how to get the complete text with apparent line breaks.
Note:
InputTextBox.ViewportWidth
. You may want to test if the final output is exactly as desired.See: Advanced Text Formatting and Advanced Text Formatting Example
Sample Code
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;
}
For that you have to write your own logic by making use of text measurement API.
STEP 1: Bresk the textbox text in to words.
STEP 2: Then measure each word width and combine them until the line width is less than textbox width.
Refer this post which explains about text measurement process. (social.msdn.microsoft.com/forums/en-US/wpf/thread/…)
See the answer by Ian Griffiths to this question: Get Displayed Text from TextBlock
It gets the displayed text (as it is presented on the screen) from a TextBlock
but I think you should be able to use it for a TextBox
as well