Example #1
0
        private static void RemoveHyperlink(AutoCompleteRichTextBox myRichTextBox, TextPointer caretPosition)
        {
            var       backspacePosition = caretPosition.GetNextInsertionPosition(LogicalDirection.Backward);
            Hyperlink hyperlink;

            if (backspacePosition == null || !DocumentUtils.IsHyperlinkBoundaryCrossed(caretPosition, backspacePosition, out hyperlink))
            {
                return;
            }

            // Remember caretPosition with forward gravity. This is necessary since we are going to delete
            // the hyperlink element preceeding caretPosition and after deletion current caretPosition
            // (with backward gravity) will follow content preceeding the hyperlink.
            // We want to remember content following the hyperlink to set new caret position at.

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

            // Deleting the hyperlink is done using logic below.

            // 1. Copy its children Inline to a temporary array.
            var hyperlinkChildren = hyperlink.Inlines;
            var 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]);
                hyperlink.SiblingInlines.InsertAfter(hyperlink, inlines[i]);
            }

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

            while (localProperties.MoveNext())
            {
                var    property = localProperties.Current;
                var    dp       = property.Property;
                object value    = property.Value;

                if (!dp.ReadOnly &&
                    dp != Inline.TextDecorationsProperty && // Ignore hyperlink defaults.
                    dp != TextElement.ForegroundProperty &&
                    dp != BaseUriHelper.BaseUriProperty &&
                    !DocumentUtils.IsHyperlinkProperty(dp))
                {
                    inlineRange.ApplyPropertyValue(dp, value);
                }
            }

            // 4. Delete the (empty) hyperlink element.
            hyperlink.SiblingInlines.Remove(hyperlink);

            // 5. Update selection, since we deleted Hyperlink element and caretPosition was at that Hyperlink's end boundary.
            myRichTextBox.Selection.Select(newCaretPosition, newCaretPosition);
        }
Example #2
0
        private void OnTextChanged(object sender, TextChangedEventArgs e)
        {
            if (!myWordsAddedFlag || Document == null)
            {
                return;
            }

            // Temporarily disable TextChanged event handler, since following code might insert Hyperlinks,
            // which will raise another TextChanged event.
            TextChanged -= OnTextChanged;

            var navigator = mySelectionStartPosition;

            while (navigator != null && navigator.CompareTo(mySelectionEndPosition) <= 0)
            {
                var wordRange = DocumentUtils.GetWordRange(navigator);
                if (wordRange == null || wordRange.IsEmpty)
                {
                    // No more words in the document.
                    break;
                }

                string wordText = wordRange.Text;
                if (IsHyperlink(wordText) &&
                    !DocumentUtils.IsInHyperlinkScope(wordRange.Start) &&
                    !DocumentUtils.IsInHyperlinkScope(wordRange.End))
                {
                    var hyperlink = new Hyperlink(wordRange.Start, wordRange.End);
                    hyperlink.NavigateUri = new Uri(wordText.StartsWith("http", StringComparison.OrdinalIgnoreCase) ? wordText : "http://" + wordText);
                    WeakEventManager <Hyperlink, RequestNavigateEventArgs> .AddHandler(hyperlink, "RequestNavigate", OnHyperlinkRequestNavigate);

                    navigator = hyperlink.ElementEnd.GetNextInsertionPosition(LogicalDirection.Forward);
                }
                else
                {
                    navigator = wordRange.End.GetNextInsertionPosition(LogicalDirection.Forward);
                }
            }

            TextChanged += OnTextChanged;

            myWordsAddedFlag         = false;
            mySelectionStartPosition = null;
            mySelectionEndPosition   = null;
        }