Tim Bailey
Tim Bailey

Reputation: 571

Silverlight Richtextbox obtain cursor position

I'm trying create a user control using the silverlight 5 richtextbox. I need to be able to insert "inline ui" and can't work out how to get the current cursor position.

I trigger my code like this:

this.GetAbsolutePos(this.richText.Selection.Start);

The guts of this method is here:

private int GetAbsolutePos(TextPointer textPointer)
{
   int index = 0;
   TextPointer pos = this.richText.ContentStart;
   while (pos.CompareTo(textPointer) != 0)
   {
      if (pos.IsAtInsertionPosition)
      {
          index++;
      }

      pos = pos.GetNextInsertionPosition(LogicalDirection.Forward);
   }
   return index;
}

Given the following text in a richtextbox control....

Empty Control

If the cursor is between 5 & 6 on the first line, then the above function correctly returns 5. But as the cursor is further into the text the position becomes more inaccurate. ie between 5 & 6 on the second line returns 16 and the third line returns 27.

It also becomes more difficult as I'm inserting inline elements at these positions, which then count as a "symbol" and further cause the count to go wrong.

This image shows what is happening when I "insert" the inline ui between 5 & 6 on each line. With 3 Inlines

Just for completeness here is the Xaml from richtext.Xaml (I've removed all the extra attributes from the Section/Paragraph elements to make it clearer)

<Section>
   <Paragraph>
       <Run>1234567890</Run>
       <LineBreak />
       <Run>1234567890</Run>
       <LineBreak />
       <Run>1234567890</Run>
   </Paragraph>
</Section> 

Based on the remarks on this page MSDN Silverlight TextPointer Class

Symbol - For TextPointer operations, any of the following is considered to be a symbol:

  • An opening or closing tag for a TextElement element.

  • A UIElement element contained within an InlineUIContainer. Note that a UIElement is always counted as exactly one symbol. Any additional content or elements contained by the UIElement are not considered symbols.

  • Each 16-bit Unicode character inside of a text Run element.

I think I need to "know" what kind of "symbol" I am currently on but cannot figure out how.

Seems like it should be easy, but working with TextPointers seems very unintuitive. I had an idea to parse the Xaml to find the cursor position but that seems like a real hack.

Any help would be appreciated.

Thanks

Upvotes: 1

Views: 1370

Answers (2)

Ichibanpanda
Ichibanpanda

Reputation: 916

I am not sure if this will help, but I ended up letting the user insert where the selection is instead of caret position and it seems to work well. Here is some of my code:

InlineUIContainer MyUI = new InlineUIContainer();
TextBlock tblx = new TextBlock() { Text = addedItem.Title, FontWeight = FontWeights.Bold };
MyUI.Child = tblx;
Paragraph myParagraph = new Paragraph();
myParagraph.Inlines.Add(MyUI);
rtb.Selection.Insert(myParagraph);

Upvotes: 0

Tim Bailey
Tim Bailey

Reputation: 571

In the end we just just manually adjust the index by the number of SubstituteEdits (our representation of the UIElement) that are before the text point. Its still flaky and we have other issues with our control, but it's good enough for the moment.

Cheers

Tim

    private int GetAbsolutePos(SubstituteEdit newSub)
    {
        int index = 0;
        TextPointer textPointer = this.richText.Selection.Start;
        TextPointer caretWhere = this.richText.ContentStart;

        while (true)
        {
            caretWhere = caretWhere.GetNextInsertionPosition(LogicalDirection.Forward);
            if (caretWhere == null || caretWhere.CompareTo(textPointer) == 0)
            {
                break;
            }

            index++;
        }

        foreach (SubstituteEdit sub in this.Substitutes)
        {
            if (sub.Position < index && sub != newSub)
            {
                index--;
            }
        }

        return index;
    }

Upvotes: 0

Related Questions