예제 #1
0
        private void RemoveHyperlinkFormat()
        {
            TextPointer caretPosition     = Selection.Start;
            TextPointer backspacePosition = caretPosition.GetNextInsertionPosition(LogicalDirection.Backward);
            Hyperlink   hyperlink         = default(Hyperlink);

            try
            {
                if (backspacePosition != null && IsHyperlinkBoundaryCrossed(caretPosition, backspacePosition, ref hyperlink))
                {
                    // Remember caretPosition with forward gravity. This is necessary since we are going to delete
                    // the hyperlink element preceding caretPosition and after deletion current caretPosition
                    // (with backward gravity) will follow content preceding the hyperlink.
                    // We want to remember content following the hyperlink to set new caret position at.

                    TextPointer newCaretPosition = caretPosition.GetPositionAtOffset(0, LogicalDirection.Forward);

                    // 1. Copy its children Inline to a temporary array
                    InlineCollection hyperlinkChildren = hyperlink.Inlines;
                    Inline[]         inlines           = new Inline[hyperlinkChildren.Count];
                    hyperlinkChildren.CopyTo(inlines, 0);

                    // 2. Remove each child from parent hyperlink element and insert it after the hyperlink
                    for (int i = inlines.Length - 1; i >= 0; i--)
                    {
                        hyperlinkChildren.Remove(inlines[i]);
                        if (hyperlink.SiblingInlines != null)
                        {
                            hyperlink.SiblingInlines.InsertAfter(hyperlink, inlines[i]);
                        }
                    }

                    // 3. Apply hyperlink local formatting properties to inlines (which are now outside hyperlink scope)
                    LocalValueEnumerator localProperties = hyperlink.GetLocalValueEnumerator();
                    TextRange            inlineRange     = new TextRange(inlines[0].ContentStart, inlines[inlines.Length - 1].ContentEnd);

                    while (localProperties.MoveNext())
                    {
                        LocalValueEntry    property           = localProperties.Current;
                        DependencyProperty dependencyProperty = property.Property;
                        object             value = property.Value;

                        // Ignore hyperlink defaults
                        if (dependencyProperty.ReadOnly == false &&
                            dependencyProperty.Equals(Inline.TextDecorationsProperty) == false &&
                            dependencyProperty.Equals(TextElement.ForegroundProperty) == false &&
                            dependencyProperty.Equals(BaseUriHelper.BaseUriProperty) == false &&
                            IsHyperlinkProperty(dependencyProperty) == false &&
                            dependencyProperty.Name.Equals("IsEnabled") == false)
                        {
                            inlineRange.ApplyPropertyValue(dependencyProperty, value);
                        }
                    }

                    // 4. Delete the (empty) hyperlink element
                    if (hyperlink.SiblingInlines != null)
                    {
                        hyperlink.RequestNavigate -= OnRequestNavigate;
                        hyperlink.SiblingInlines.Remove(hyperlink);
                    }

                    // 5. Update selection, since we deleted Hyperlink element and caretPosition was at that hyperlink's end boundary
                    Selection.Select(newCaretPosition, newCaretPosition);
                }
            }
            catch (Exception ex)
            {
                Log.Error("Error while removing hyperlink format: {EX}", ex);
            }
        }