示例#1
0
        /// <summary>
        /// Event handler for RichTextBox.TextChanged event.
        /// </summary>
        private void TextChangedEventHandler(object sender, TextChangedEventArgs e)
        {
            if (!this.pasteFlag || this.Document == null)
            {
                return;
            }

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

            TextPointer navigator = this.Document.ContentStart;

            while (navigator != null && navigator.CompareTo(this.Document.ContentEnd) < 0)
            {
                TextRange wordRange = WordBreaker.GetWordRange(navigator);
                if (wordRange == null || wordRange.IsEmpty)
                {
                    // No more words in the document.
                    break;
                }

                string wordText = wordRange.Text;
                if (wordText == "www.microsoft.com" &&
                    !HyperlinkHelper.IsInHyperlinkScope(wordRange.Start) &&
                    !HyperlinkHelper.IsInHyperlinkScope(wordRange.End))
                {
                    Hyperlink hyperlink = new Hyperlink(wordRange.Start, wordRange.End);
                    navigator = hyperlink.ElementEnd.GetNextInsertionPosition(LogicalDirection.Forward);
                }
                else
                {
                    navigator = wordRange.End.GetNextInsertionPosition(LogicalDirection.Forward);
                }
            }

            this.TextChanged += this.TextChangedEventHandler;
            this.pasteFlag    = false;
        }
示例#2
0
        /// <summary>
        /// Event handler for KeyDown event to auto-detect hyperlinks on space, enter and backspace keys.
        /// </summary>
        private static void OnKeyDown(object sender, KeyEventArgs e)
        {
            MyRichTextBox myRichTextBox = (MyRichTextBox)sender;

            if (e.Key != Key.Back && e.Key != Key.Space && e.Key != Key.Return)
            {
                return;
            }

            if (!myRichTextBox.Selection.IsEmpty)
            {
                myRichTextBox.Selection.Text = String.Empty;
            }

            TextPointer caretPosition = myRichTextBox.Selection.Start;

            if (e.Key == Key.Space || e.Key == Key.Return)
            {
                TextRange wordRange = WordBreaker.GetWordRange(caretPosition);
                string    wordText  = wordRange.Text;

                if (wordText == "www.microsoft.com")
                {
                    // Insert hyperlink element at word boundaries.
                    new Hyperlink(wordRange.Start, wordRange.End);

                    // No need to update RichTextBox caret position,
                    // since we only inserted a Hyperlink ElementEnd following current caretPosition.
                    // Subsequent handling of space input by base RichTextBox will update selection.
                }
            }
            else // Key.Back
            {
                TextPointer backspacePosition = caretPosition.GetNextInsertionPosition(LogicalDirection.Backward);
                Hyperlink   hyperlink;
                if (backspacePosition != null && HyperlinkHelper.IsHyperlinkBoundaryCrossed(caretPosition, backspacePosition, out hyperlink))
                {
                    // 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.

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

                    // Deleting the hyperlink is done using logic below.

                    // 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]);
                        hyperlink.SiblingInlines.InsertAfter(hyperlink, inlines[i]);
                    }

                    // 3. Apply hyperlink's 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 dp       = property.Property;
                        object             value    = property.Value;

                        if (!dp.ReadOnly &&
                            dp != Inline.TextDecorationsProperty && // Ignore hyperlink defaults.
                            dp != TextElement.ForegroundProperty &&
                            dp != BaseUriHelper.BaseUriProperty &&
                            !HyperlinkHelper.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);
                }
            }
        }