6

Here is the deal: I have a RichTextBox control and it works fine. The problem is that there is a button "Insert Current DateTime" which adds/injects the current datetime into the RichTextBox. The user can enter the datetime anywhere where the caret is pointing. This involves complicated string manipulation and stuff.

Any ideas how to get the current caret position. Whenever I get RichTextBox.CaretPositon it seems it is pointing to the start of the RichTextBox and not where the actual caret is.

UPDATE 1:

The date time button click code:

 private void DateTimeStampButton_Click(object sender, RoutedEventArgs e)
        {
            //TextRange tr = new TextRange(textBox.Selection.Start, textBox.Selection.End);
            var tr = new TextRange(textBox.Document.ContentStart, textBox.Document.ContentEnd);

            if(tr.Text.Length == 2)
            {
                if(tr.Text == "\r\n")
                {
                    tr.Text = tr.Text.TrimStart(new[] { '\r', '\n' }); 
                }
            }

            textBox.CaretPosition.InsertTextInRun(DateTime.Now.ToShortDateString() + " " + DateTime.Now.ToShortTimeString() + ":  ");

            DateTimeStampButton.Focusable = false;
        }

 private void SharpRichTextBox_LostFocus(object sender, RoutedEventArgs e)
        {
            SetValue(TextProperty, Text);

            var binding = BindingOperations.GetBinding(this, TextProperty);

            if (binding == null) return;

            if (binding.UpdateSourceTrigger == UpdateSourceTrigger.Default || binding.UpdateSourceTrigger == UpdateSourceTrigger.LostFocus)
            {
                // if (TextProperty != null) BindingOperations.GetBindingExpression(this, TextProperty).UpdateSource();
            }
        }






public string Text
        {
            get
            {
                var newValue = new TextRange(Document.ContentStart, Document.ContentEnd).Text.RemoveNewLineAndReturn(); 
                return newValue; 
            }
            set
            {
                if (!String.IsNullOrEmpty(value))
                {
                    SetValue(TextProperty, value.RemoveNewLineAndReturn());
                    Document.Blocks.Clear(); 
                    Document.Blocks.Add(new Paragraph(new Run(value))); 
                    OnPropertyChanged("Text"); 
                }
            }
        }

UPDATE 2:

Turned out the problem was with the DateTime button being Focusable. I turned it to be not focusable and it worked as expected. When focus was lost on the RichTextBox it was resetting the caret position. It happened only once since in the code the btn_DateTime was dynamically being set as Focusable = false. I placed Focusable = false in XAML and everything worked fine from the start.

Dave Clemmer
  • 3,741
  • 12
  • 49
  • 72
azamsharp
  • 19,710
  • 36
  • 144
  • 222
  • I really wish I knew what to tell you. According to documentation, a RichTextBox's CaretPosition is supposed to be the current position, or the start of the RichTextBox if the user hasn't moved it/typed anything. – Powerlord Feb 08 '10 at 19:56
  • Is there a way to get the RichTextBox inputted string's index number from the CaretPosition. Like if the string is "hellow" and the carret is at he|llow then it should return 2. – azamsharp Feb 08 '10 at 20:09

3 Answers3

14

I'm using this code to successfully do what you are attempting:

private void insertNowButton_Click(object sender, RoutedEventArgs e)
{
    //NOTE:  The caret position does not change.
    richTextBox1.CaretPosition.InsertTextInRun(DateTime.Now.ToString());
}

EDIT: Addressing Update 1

private void DateTimeStampButton_Click(object sender, RoutedEventArgs e)
{
    var tr = new TextRange(textBox.Document.ContentStart, textBox.Document.ContentEnd);

    if (tr.Text.Length == 2)
    {
        if (tr.Text == "\r\n")
        {
            tr.Text = tr.Text.TrimStart(new[] { '\r', '\n' });
        }
    }

    /* Changing the text is the only way I can get the date to insert at the beginning */
    tr.Text = "I need a beer at ";

    textBox.CaretPosition.InsertTextInRun(DateTime.Now.ToString());
}

It looks like SetValue is changing the text so based on my test that actually changing the text resets the caret, I would agree with you that SetValue is causing the problem...

Austin Salonen
  • 49,173
  • 15
  • 109
  • 139
  • Awesome! This is it. I just have one minor problem. If I type "hello datetime is" and press the "insert datetime" button. Then it shows up like this: 02/08/2010 2:27 PM hello datetime is. As, you can see for some reason datetime is prefixing the text. If I remove it and set the cursor at the end of the hello datetime text and then press the button again then it works fine. In my RichTextBox I set textBox.CaretPosition = Document.ContentEnd; – azamsharp Feb 08 '10 at 20:28
  • In my simple app (WPF with one RichTextBox, one TextBox, and one Button), it always puts it where the caret is flashing. With another control that steals the caret, it inserts where the caret was last. My advice: remove all the code that does anything with the caret and try again. – Austin Salonen Feb 08 '10 at 20:43
  • Thanks for the suggestion! I went through the complete solution and could not found any other reference to the caret. – azamsharp Feb 08 '10 at 20:49
  • Another interesting thing I noted. If I type "hello " then the caret is at the end of the o like "hello |" and I press the date button it does not insert at that position. But if I click the mouse at the same location then it works fine. There is something fishy about this problem. – azamsharp Feb 08 '10 at 20:52
  • @azamsharp: Without any code posted, this snippet is the best advice I can give. In my simple form, I can type "the current time is: " (which gives "the current time is: |" with a caret; press the button linked to the above code; and get "the current time is: 2/8/2010 3:00:57 PM". You'll have to post more code to clear up any fishiness. – Austin Salonen Feb 08 '10 at 21:05
  • I think the problem lies in the SetValue call inside the Lost_Focus event. – azamsharp Feb 08 '10 at 21:15
  • It think I figured it out. It was because the DateTime button was not set as Focusable= false. every time the date time button got focused the textbox loses the focus. – azamsharp Feb 08 '10 at 21:47
3

I tried this solution with WPFToolkit.Extended RichTextBox and it didn't work for me. However I found another one and thought it would be good to post it in here in case someone else could use it.

My problem was also that the after I clicked a button that is supposed to append text at the caret location, it instead adds it at the beginning of the RichTextBox.

So The solution I found is similar to the one in here -

RichTextBox CaretPosition physical location

Instead of using CaretPosition I used RichTextBox.Selection.Start.InsertTextInRun("SomeText").

It considered the selection's start as the caret position even though no selection was made and therefore was good enough for me.

I hope someone will find this useful :)

Community
  • 1
  • 1
Dror
  • 2,548
  • 4
  • 33
  • 51
2

This worked for me:

private void InsertText(String text, RichTextBox rtb)
{
    rtb.CaretPosition = rtb.CaretPosition.GetPositionAtOffset(0, LogicalDirection.Forward);
    rtb.CaretPosition.InsertTextInRun(text);
}

I found the code here:

How do I move the caret a certain number of positions in a WPF RichTextBox?

Community
  • 1
  • 1
XSapien
  • 152
  • 2
  • 11