C# 在保留插入符号的同时替换文档中的文本

C# 在保留插入符号的同时替换文档中的文本,c#,mef,document,visual-studio-extensions,C#,Mef,Document,Visual Studio Extensions,我正在开发一个扩展,它使用外部程序在VisualStudio中格式化代码 如果我使用ITextEdit.replace(…)替换文件的内容,插入符号将放在文档的末尾,这是错误的 我试图做的是在替换文件内容之前在textbuffer中保存当前插入符号位置的快照,然后在替换内容之前将插入符号位置设置为它以前在textbuffer中的位置 但是,ITextEdit.Apply()正在生成新快照,导致\u textView.Caret.MoveTo(point)引发异常: System.Argument

我正在开发一个扩展,它使用外部程序在VisualStudio中格式化代码

如果我使用ITextEdit.replace(…)替换文件的内容,插入符号将放在文档的末尾,这是错误的

我试图做的是在替换文件内容之前在textbuffer中保存当前插入符号位置的快照,然后在替换内容之前将插入符号位置设置为它以前在textbuffer中的位置

但是,ITextEdit.Apply()正在生成新快照,导致\u textView.Caret.MoveTo(point)引发异常:

System.ArgumentException: The supplied SnapshotPoint is on an incorrect snapshot.
Parameter name: bufferPosition
at Microsoft.VisualStudio.Text.Editor.Implementation.CaretElement.InternalMoveTo(VirtualSnapshotPoint bufferPosition, PositionAffinity caretAffinity, Boolean captureHorizontalPosition, Boolean captureVerticalPosition, Boolean raiseEvent)
at Microsoft.VisualStudio.Text.Editor.Implementation.CaretElement.MoveTo(SnapshotPoint bufferPosition)
我还尝试创建一个新的快照点,而不是使用_textView.Caret.Position.BufferPosition,如下所示:

var point = new SnapshotPoint(_textView.TextSnapshot, 0);
引发相同的“提供的快照点位于不正确的快照上”异常

public class MyCommand
{
    private readonly IWpfTextView _textView;
    private readonly MyFormatter _formatter;
    private readonly ITextDocument _document;

    public MyCommand(IWpfTextView textView, MyFormatter formatter, ITextDocument document)
    {
        _textView = textView;
        _formatter = formatter;
        _document = document;
    }

    public void Format()
    {
        var input = _document.TextBuffer.CurrentSnapshot.GetText();
        var output = _formatter.format(input);

        // get caret snapshot point
        var point = _textView.Caret.Position.BufferPosition;

        using (var edit = _document.TextBuffer.CreateEdit())
        {
            edit.Replace(0, _document.TextBuffer.CurrentSnapshot.Length, output);
            edit.Apply();
        }

        // set caret position
        _textView.Caret.MoveTo(point);
    }
}
我不想实现一些定制的插入符号“历史”,我想按照它的本意去做。 此外,我希望移动插入符号被视为编辑的一部分,保持“ctrl+z”功能完好无损


一如既往,我们非常感谢您的帮助

您可以检索点的位置,然后创建新的快照点并移动到该点

像这样:

var point = _textView.Caret.Position.BufferPosition;
int position = point.Position;

        using (var edit = _document.TextBuffer.CreateEdit())
        {
            edit.Replace(0, _document.TextBuffer.CurrentSnapshot.Length, output);
            edit.Apply();
        }

        // set caret position
        _textView.Caret.MoveTo(new SnapshotPoint(_textView.TextSnapshot, position));
此外,您还可以创建和使用如下扩展:

尽管科尔·吴(Cole Wu-MSFT)对我的问题的回答帮助我解决了问题,但它并没有完全满足我的要求:

使用提供的代码可以移动插入符号,但是,由于我替换了文档的全部内容,因此它也会将滚动位置重置为顶部,即使插入符号位于文档的更下方

另外:这仍然会生成“多个撤消”,而不是一个撤消:即,替换文档内容和移动插入符号是两个单独的“撤消”,这需要用户按两次CTRL+Z,而不是只按一次来撤消替换

为了解决这个问题,我将代码更改为:

public class MyCommand
{
    private readonly IWpfTextView _textView;
    private readonly MyFormatter _formatter;
    private readonly ITextDocument _document;
    private readonly ITextBufferUndoManager _undoManager;

    public MyCommand(IWpfTextView textView, MyFormatter formatter, ITextDocument document, ITextBufferUndoManager undoManager)
    {
        _textView = textView;
        _formatter = formatter;
        _document = document;
        _undoManager = undoManager;
    }

    public void Format()
    {
        var input = _textView.TextSnapshot.GetText();
        var output = _formatter.format(input);

        using (var undo = _undoManager.TextBufferUndoHistory.CreateTransaction("Format"))
        using (var edit = _undoManager.TextBuffer.CreateEdit(EditOptions.DefaultMinimalChange, 0, null))
        {
            edit.Replace(0, _textView.TextSnapshot.Length, output);
            edit.Apply();

            undo.Complete();
        }
    }
}
这并不是我想要的方式,因为插入符号有时(位于尾随空格处)会跳到下一行的开头,而不是当前行的结尾


然而,它已经足够近了

谢谢您的帮助@coleWuMsft-请参阅下面我接受的答案。
\u文档的来源在哪里?