我正在开发一个依赖AvalonEdit来管理文档的项目。本文档中的某些行被标记为使用无法从AvalonEdit中修改的特定缩进。
我已经设法通过VisualLineElements
在这些标记行的开头注入来实现这一点。视觉元素具有缩进的 aDocumentLength
和0
aVisualLength
大小。我还重写了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
在文档的实际内容和它的呈现方式之间保持清晰的分离。