Detect when caret position changes in RichTextBox

2019-08-12 20:08发布

问题:

I am trying to implement very simple text formatting functionality for a RichTextBox in WPF. This just consists of a few bold, italic, etc ToggleButtons just above the RichTextBox. See image below, but ignore the top TextBox - the RichTextBox is the bigger one at the bottom.

Toggling formatting for either a selection or at the caret position (for text that will be typed in) is not a problem, as I'm doing this:

    private void BoldButton_Checked(object sender, RoutedEventArgs e)
    {
        this.SetSelectionBold(true);
    }

    private void BoldButton_Unchecked(object sender, RoutedEventArgs e)
    {
        this.SetSelectionBold(false);
    }

    private void SetSelectionBold(bool isBold)
    {
        var selection = this.RichText.Selection;
        if (selection != null)
        {
            selection.ApplyPropertyValue(TextElement.FontWeightProperty, isBold ? FontWeights.Bold : FontWeights.Normal);
        }
    }

However, if the user moves the caret somewhere else (e.g. from bold text to normal text) then I'd like the ToggleButtons to reflect that state, in much the same way as it works in Word. Is it possible to detect when the caret position changes, and take action accordingly?

回答1:

Hook yourself into SelectionChanged event and get current caret position, and test if the property exists on that selection?

In the event, probably you want something like:

var selection = richTextBox.Selection;
if(selection != null)
{
  if(selection.GetPropertyValue(TextElement.FontWeightProperty) == FontWeights.Bold)
    // todo; enable your button
}

If that event is not triggered by caret positioning(the document doesn't say anything about that), you probably need to inherit from RichTextBox and override OnSelectionChanged, after that you need to actually generate your own Caret, eg:

var currentCaretPlusOne = new TextRange(richTextBox.CaretPosition, 
                  richTextBox.CaretPosition+1);
if(currentCaretPlusOne != null)
{
   if(currentCaretPlusOne.GetPropertyValue(TextElement.FontWeightProperty)
             == FontWeights.Bold)
        // todo; enable your button
}