私はAvalonEditを使用していますが、エディターにフォーカスがない場合でも、ユーザーが常にカレットがどの行にあるかを確認できるようにしたいと考えています。そのために、BackgroundRendererを使用して現在の行の背景を強調表示するコードを見つけて適合させました。
残念ながら、エディターがフォーカスされていないときにCaretOffsetを変更すると、エディターがフォーカスを失ったときに現在の行に、背景の長方形が配置されたままになります。エディターが再びフォーカスを取得するまで、新しい現在の行に同期されません。
私はこれがなぜ起こっているのかを理解しました(それを修正する方法ではありません)。IBackgroundRendererのドキュメントコメントによると、「バックグラウンドレンダラーは、関連する既知のレイヤーが描画することを選択した場合にのみ描画します。たとえば、カレットレイヤーのバックグラウンドレンダラーは、カレットが非表示の場合は非表示になります。」私のバックグラウンドレンダラーはKnownLayer.Caretに存在するので、そうです、エディターがフォーカスされていないときに更新されない理由がわかります。これは、カレットも非表示になっているためです。(それを考えると、私の長方形が表示されたままであることに実際に驚いています。)
CaretOffsetを設定した直後にtextEditor.TextArea.TextView.InvalidateLayer(KnownLayer.Caret)を明示的に呼び出しようとしましたが、効果はありませんでした。キャレットが非表示になっているため、呼び出しは無視されたと思います。
エディターにフォーカスがない場合でも、現在の行のハイライトを強制的に更新するための最良の方法は何ですか?
これが私のクラスのコードです。私は確かにこれを捨てて、それを行うためのより良い方法があれば別のアプローチをすることにオープンです。
public class HighlightCurrentLineBackgroundRenderer : IBackgroundRenderer
{
private TextEditor _editor;
public HighlightCurrentLineBackgroundRenderer(TextEditor editor)
{
_editor = editor;
}
public KnownLayer Layer
{
get { return KnownLayer.Caret; }
}
public void Draw(TextView textView, DrawingContext drawingContext)
{
if (_editor.Document == null)
return;
textView.EnsureVisualLines();
var currentLine = _editor.Document.GetLineByOffset(_editor.CaretOffset);
foreach (var rect in BackgroundGeometryBuilder.GetRectsForSegment(textView, currentLine))
{
drawingContext.DrawRectangle(
new SolidColorBrush(Color.FromArgb(0x40, 0, 0, 0xFF)), null,
new Rect(rect.Location, new Size(textView.ActualWidth - 32, rect.Height)));
}
}
}
次に、UserControlのコンストラクターで、レンダラーをエディターに追加します。
textEditor.TextArea.TextView.BackgroundRenderers.Add(
new HighlightCurrentLineBackgroundRenderer(textEditor));