AvalonEdit WPF TextEditor (SharpDevelop): How to highlight a specific range of text?

后端 未结 4 922
温柔的废话
温柔的废话 2020-12-30 14:24

The incredibly awesome AvalonEdit WPF TextEditor control seems to lack an important feature, or at least i can\'t figure it out. Given an offset and a length, highli

相关标签:
4条回答
  • 2020-12-30 14:59

    Some background info: AvalonEdit is a code editor, not a rich text editor. There is no such thing as "highlight a portion of the document" - the document only stores plain text.

    Highlighting is computed on-demand, only for the lines currently in view. If you want custom highlighting, you need to add a step to the highlighting computation - this is what the ColorizeAvalonEdit class in the example posted by mzabsky is doing.

    0 讨论(0)
  • 2020-12-30 15:00

    You need to create a custom ColorizingTransformer to do that. The above example is actually highlighting a specific word. Still, you can change it a little bit to to colorize or highlight a portion.

    I used Avalon TextEditor for my Console+ project (which is in a very primitive stage at the moment)

    public class OffsetColorizer : DocumentColorizingTransformer
    {
        public int StartOffset { get; set; }
        public int EndOffset { get; set; }
    
        protected override void ColorizeLine(DocumentLine line)
        {
            if (line.Length == 0)
                return;
    
            if (line.Offset < StartOffset || line.Offset > EndOffset)
                return;
    
            int start = line.Offset > StartOffset ? line.Offset : StartOffset;
            int end = EndOffset > line.EndOffset ? line.EndOffset : EndOffset;
    
            ChangeLinePart(start, end, element => element.TextRunProperties.SetForegroundBrush(Brushes.Red));
        }
    }
    

    And you can add the colorizer to the editor by adding it to LineTransformers collection.

    tbxConsole.TextArea.TextView.LineTransformers.Add(_offsetColorizer);
    
    0 讨论(0)
  • 2020-12-30 15:13

    Did you see this in this article - it seems to be exactly what are you asking for:

    public class ColorizeAvalonEdit : DocumentColorizingTransformer
    {
    protected override void ColorizeLine(DocumentLine line)
    {
        int lineStartOffset = line.Offset;
        string text = CurrentContext.Document.GetText(line);
        int start = 0;
        int index;
        while ((index = text.IndexOf("AvalonEdit", start)) >= 0) {
            base.ChangeLinePart(
                lineStartOffset + index, // startOffset
                lineStartOffset + index + 10, // endOffset
                (VisualLineElement element) => {
                    // This lambda gets called once for every VisualLineElement
                    // between the specified offsets.
                    Typeface tf = element.TextRunProperties.Typeface;
                    // Replace the typeface with a modified version of
                    // the same typeface
                    element.TextRunProperties.SetTypeface(new Typeface(
                        tf.FontFamily,
                        FontStyles.Italic,
                        FontWeights.Bold,
                        tf.Stretch
                    ));
                });
            start = index + 1; // search for next occurrence
    }   }   }
    

    It highlights word AvalonEdit with bold.

    0 讨论(0)
  • 2020-12-30 15:18

    I know this is a pretty old question, but I thought I would share my solution. I am not sure if this solution has been implemented into AvalonEdit, since this question was originally answered, but I find the OffsetColorizer class doesn't actually select the line: it just changes the line's background colour.

    My solution is as follows:

    textEditor.SelectionStart = offset;
    
    textEditor.SelectionLength = length;
    

    However, this can be extended further like so:

    public void SelectText(int offset, int length)
    {
        //Get the line number based off the offset.
        var line = textEditor.Document.GetLineByOffset(offset);
        var lineNumber = line.LineNumber;
    
        //Select the text.
        textEditor.SelectionStart = offset;
        textEditor.SelectionLength = length;
    
        //Scroll the textEditor to the selected line.
        var visualTop = textEditor.TextArea.TextView.GetVisualTopByDocumentLine(lineNumber);
        textEditor.ScrollToVerticalOffset(visualTop); 
    }
    

    I find that this solution works better is that rather than just colouring the line, it actually selects it: meaning it can be copied using Ctrl+C.

    I Hope this helps people in the future.

    0 讨论(0)
提交回复
热议问题