开发者

WPF: Get "wrapped" text out of a textbox

Is there a way in WPF to get the te开发者_高级运维xt formatted as it display on the textbox when TextWrapping="Wrap"?

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

I've tried to use TextFormatter class, but it onty allow me to draw the text to a drawing context where i only need the text with line break included.


Here's how to get the complete text with apparent line breaks.

Note:

  • Include the following classes from Advanced Text Formatting Example in your project:
    • CustomTextSource
    • FontRendering
    • GenericTextProperties
  • There are some limitations which are mentioned in CustomTextSource class. However, I believe your requirements aren't impacted by those limitations.
  • These are just examples. You may want to modify code as per your needs.
  • The code still uses a hack (although a decent one) - 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;
}


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


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/…)


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜