0

我正在开发一个依赖AvalonEdit来管理文档的项目。本文档中的某些行被标记为使用无法从AvalonEdit中修改的特定缩进。

我已经设法通过VisualLineElements在这些标记行的开头注入来实现这一点。视觉元素具有缩进的 aDocumentLength0aVisualLength大小。我还重写了GetNextCaretPosition将插入符号“推”到左侧VisualLineElement(在向后移动的情况下)或向右(在向前移动的情况下)的方法。

这是我VisualLineElement的格式减少的版本(请注意,元素总是在 处注入VisualColumn == 0):

public class MyLineFormatElement : VisualLineElement
{
    private readonly string _elementText;

    public MyLineFormatElement (string elementText)
        : base(elementText.Length, 0)
    {
        _elementText = elementText;
    }

    public override bool CanSplit
    {
        get
        {
            return false;
        }
    }

    public override int GetNextCaretPosition(int visualColumn, System.Windows.Documents.LogicalDirection direction, ICSharpCode.AvalonEdit.Document.CaretPositioningMode mode)
    {
        if (visualColumn >= VisualColumn && visualColumn <= VisualColumn + VisualLength)
        {
            return direction == LogicalDirection.Forward ? VisualColumn + VisualLength : VisualColumn;
        }

        return base.GetNextCaretPosition(visualColumn, direction, mode);
    }

    public override TextRun CreateTextRun(int startVisualColumn, ITextRunConstructionContext context)
    {
        return new TextCharacters(_elementText, TextRunProperties);
    }
}

这很好用,除了我遇到的一个问题:我仍然可以将插入符号放在行首。从用户的角度来看,这非常令人困惑。更糟糕的是,在行首按“delete”或在缩进末尾按“退格”只会移动插入符号而不进行任何修改。据我了解,如果无法将插入符号放在行首(基于 中的代码CaretNavigationCommandHandler.OnMoveCaret),删除/退格问题将得到解决。

对于如何解决这个问题,我最好的猜测是覆盖HandlesLineBorders属性,使其返回 true,然后进行修改GetNextCaretPosition,以便: 1. 在元素上向前移动时,return VisualColumn + VisualLength(已经是这种情况) 2. 在元素上向后移动时,返回上一行的最后一个视觉列(我不知道该怎么做)

#2的最后一部分可能吗?如果是这样,我该怎么做?如果没有,我应该尝试其他方法吗?我真的很想坚持VisualLineElements在文档的实际内容和它的呈现方式之间保持清晰的分离。

4

1 回答 1

1

只需返回-1;这表示您VisualLineElement(在搜索方向)内不再有插入符号停止。

AvalonEdit 4.1 中的NewLineTextElement(表示一行结束的符号)是使用相同的方法实现的(但在实现虚拟空间时,4.2 中的实现有所改变)。

您还应该覆盖IsWhitespace并返回 true。这在 AvalonEdit 尝试检测缩进时很重要(当 word-wrap 和options.InheritWordWrapIndentation启用时)。

于 2013-05-23T21:38:07.907 回答