CustomRichTextBox StrikeThrough TextDecoration

1.3k views Asked by At

I want to add a TextDecorations.Strikethrough decoration button to my custom RichTextBox i am using the code bellow for adding and removing the TextDecoration the thing is that i am getting an InvalidCastException: Unable to cast object of type 'MS.Internal.NamedObject' to type 'System.Windows.TextDecorationCollection'. when i am selecting a range greater than the one that is strikedthrough and clicking the "StrikeThrough" button.

My Code

private void StrikeOutButton_Click(object sender, RoutedEventArgs e)
    {
        TextRange range = new TextRange(this.MyRichTextBox.Selection.Start,
                                      this.MyRichTextBox.Selection.End);

        TextDecorationCollection tdc =
            (TextDecorationCollection)this.MyRichTextBox.
                 Selection.GetPropertyValue(Inline.TextDecorationsProperty);
        /*
        if (tdc == null || !tdc.Equals(TextDecorations.Strikethrough))
        {
            tdc = TextDecorations.Strikethrough;
        }
        else
        {
            tdc = new TextDecorationCollection();
        }
         * */
        if (tdc == null || !tdc.Contains(TextDecorations.Strikethrough[0]))
        {
            tdc = TextDecorations.Strikethrough;
        }
        else
        {
            tdc = new TextDecorationCollection();
        }

        range.ApplyPropertyValue(Inline.TextDecorationsProperty, tdc);
    }

the comment out code is also not working.

I was going to post the ExceptionDetails but i think that it's very clear.

Can someone provide me a workaround?

1

There are 1 answers

1
Carpi On BEST ANSWER

The issue is that you will get DependencyProperty.UnsetValue if not your complete text is either decorated with Strikethrough or not.

So you may check for DependencyProperty.UnsetValue and just apply Strikethrough in that case.

I made a short test and this solutions works for me:

private void StrikeOutButton_Click(object sender, RoutedEventArgs e)
    {
        TextRange textRange = new TextRange(TextBox.Selection.Start, TextBox.Selection.End);
        var currentTextDecoration = textRange.GetPropertyValue(Inline.TextDecorationsProperty);

        TextDecorationCollection newTextDecoration;

        if (currentTextDecoration != DependencyProperty.UnsetValue)
            newTextDecoration = ((TextDecorationCollection)currentTextDecoration == TextDecorations.Strikethrough) ? new TextDecorationCollection() : TextDecorations.Strikethrough;
        else
            newTextDecoration = TextDecorations.Strikethrough;

        textRange.ApplyPropertyValue(Inline.TextDecorationsProperty, newTextDecoration);
    }