WPF richTextBox question

老子叫甜甜 提交于 2019-12-21 04:56:11

问题


If a line of text is wrapped to an additional line, how do I determine programmatically the point in the string where it was broken.

Example: Input string = "This is a test of a wrapped line of text".

      Based on the width of the richTextBox it could display:


            This is a test of a wrapped line of
            text.

What I need to determine is offset in the line of the word(s) that got wrapped. In the above case the word "text".

When I extract the Xaml from the richTextBox, I get the original text unwrapped.

Thanks,

Bob Kerlinger


回答1:


The trick I found uses the TextPointer class and its GetCharacterRec method.

RichTextBox holds a FlowDocument. Text in flow documents is contained in a Run object (bit of a simplification, but it works). The code finds the TextPointer at the start of the first Run. It then gets the bounding rectangle of that first character. Next the code walks forward one character at a time, gets a new bounding rectangle and checks if the bottom of the new rectangle is different from the original rectangle. If the bottom is different then we are on a new line. TextPointer can then get the text either before or after the break.

public partial class Window1 : Window
{
    public Window1()
    {
        InitializeComponent();
    }

    private void inspect(object sender, RoutedEventArgs e)
    {
        TextPointer pointer = FindRun(inBox.Document);

        string textAfterBreak = FindBreak(pointer);

        outBox.Text = textAfterBreak;
    }

    private string FindBreak(TextPointer pointer)
    {
        Rect rectAtStart = pointer.GetCharacterRect(LogicalDirection.Forward);

        pointer = pointer.GetNextInsertionPosition(LogicalDirection.Forward);
        Rect currentRect = pointer.GetCharacterRect(LogicalDirection.Forward);

        while (currentRect.Bottom == rectAtStart.Bottom)
        {
            pointer = pointer.GetNextInsertionPosition(LogicalDirection.Forward);
            currentRect = pointer.GetCharacterRect(LogicalDirection.Forward);
        }

        string textBeforeBreak = pointer.GetTextInRun(LogicalDirection.Backward);
        string textAfterBreak = pointer.GetTextInRun(LogicalDirection.Forward);

        return textAfterBreak;
    }

    private TextPointer FindRun(FlowDocument document)
    {
        TextPointer position = document.ContentStart;

        while (position != null)
        {
            if (position.Parent is Run)
                break;

            position = position.GetNextContextPosition(LogicalDirection.Forward);
        }

        return position;
    }
}

<Window x:Class="LineBreaker.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
        </Grid.RowDefinitions>
        <RichTextBox Grid.Row="0" Name="inBox">
        </RichTextBox>
        <Button Grid.Row="1" Click="inspect">Find Break</Button>
        <TextBox Name="outBox" Grid.Row="2"/>
    </Grid>
</Window>



回答2:


http://msdn.microsoft.com/en-us/library/system.windows.documents.textpointer.getlinestartposition.aspx

TextPointer startOfFirstLine = richTextBox.Document.ContentStart;
TextPointer startOfNextLine = startOfFirstLine.GetLineStartPosition(1);
if(startOfNextLine != null)
{
     // At this point what you do with the TextPointer depends on what you define as the position of text.
     // If you want to find out how many characters are on the first line ...
    int firstLineCharacterCount = new TextRange(startOfFirstLine, startOfNextLine).Text.Length;
}



回答3:


But startOfFirstLine.GetLineStartPosition(1) returns null



来源:https://stackoverflow.com/questions/306679/wpf-richtextbox-question

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!