3

VisualStudioコードウィンドウのコンテキストメニューで特定の機能を提供するVSPackageを作成しました。このアクションは、いくつかのコード編集に加えて、いくつかのもので構成されています。

問題は、これらのコード編集のそれぞれが個別にUNDOスタックに追加されることです。私が欲しいのは、このアクションを1つのアトミックユニットとして処理することです。つまり、CTRL + Zを押すと、すべてのコード編集とその他すべてがロールバックされます(もちろん、ユニットはREDOスタックの一番上に配置されます)。

このトピックに関するドキュメントは非常に貧弱で、私が見つけたのはIOleParentUndoユニットに関するものだけですが、実装に成功しませんでした。

私が使う

IVsTextLines.GetUndoManager()

元にしいマネージャーを取得するには-それは良いスタートのようです。

4

3 に答える 3

1

UNDOがドキュメントレベルで管理されている場合は、RunningDocumentTableを使用してテーブルを列挙し、UNDOマネージャーを取得して、軌道から削除する必要があります。

class NavigateListener: IVsRunningDocTableEvents3
{
    private HashSet<IVsTextView> views = new HashSet<IVsTextView>();
    private IVsRunningDocumentTable table;
    private uint cookie;
...

外では、この登録呼び出しを呼び出します-イベントの通知を解除する登録解除呼び出しを追加します。

public void Register()
{
    table =(IVsRunningDocumentTable)    Package.GetGlobalService(typeof(SVsRunningDocumentTable));
    // Listen to show/hide events of docs to register activate/deactivate cursor  listeners.
    table.AdviseRunningDocTableEvents(this, out cookie);
}

実行中のテーブルには、保存などのイベントがたくさんありますが、ビューが登録されると聞くことができます。

public int OnAfterDocumentWindowHide(uint docCookie, IVsWindowFrame pFrame)
{
    IVsTextView view = VsShellUtilities.GetTextView(pFrame);
    if (view != null)
    {
        views.Add(view);
    }
}

変更が保存されたが閉じられたドキュメントで問題が発生する可能性があります...今のところそれらを削除してください...

public int OnBeforeDocumentWindowShow(uint docCookie, int fFirstShow, IVsWindowFrame pFrame)
{
    IVsTextView view = VsShellUtilities.GetTextView(pFrame);
    if (view != null)
    {
        views.Remove(view);
    }
    return VSConstants.S_OK;
}

その後、スーパーアンドゥ核を行うことができます。私はこの部分をテストしていません-あなたはそれで遊ぶ必要があります。

private void NukeFromOrbit()
{
    foreach( var view in views )
    {
        IVsTextLines buffer;
        view.GetBuffer(out buffer);
        IOleUndoManager manager;
        buffer.GetUndoManager(out manager);
        IEnumOleUndoUnits units;
        manager.EnumUndoable(out units);
        uint fetched=0;
        var unitArray = new IOleUndoUnit[1];
        while( units.Next(1, unitArray , out fetched ) == VSConstants.S_OK)
        {
            unitArray[0].Do(manager);
        }
    }
}
于 2012-05-23T15:16:29.317 に答える
1

次のようなものを使用してみてください。

IDesignerHost host = ...;
DesignerTransaction transaction = host.CreateTransaction("Command Name");
try
{
  // Command Body
  TypeDescriptor.GetProperties(control)["Location"].SetValue(control, location);
  transaction.Commit();
}
catch
{
    transaction.Cancel();
    throw;
}
于 2012-06-26T00:44:34.587 に答える
1

以下のコードをカプセル化して、いくつかのアクションを元に戻しました。

public class VSUndo : IDisposable
{
    public static UndoContext undoContext;

    public static VSUndo StartUndo()
    {
        undoContext = ((DTE2)Package.GetGlobalService(typeof(DTE))).UndoContext; 
        undoContext.Open(Guid.NewGuid().ToString());
        // return new instance for calling dispose to close current undocontext
        return new VSUndo(); 
    }

    public void Dispose()
    {
        undoContext.Close();
    }

}

次に、次を使用できます。

using (VSUndo.StartUndo())
{
   // couple of actions that may need to undo together
}
于 2012-07-17T09:01:19.260 に答える