我创建了VSPackage,它在Visual Studio代码窗口上下文菜单中提供了某些功能。此操作包含多个代码编辑以及一些内容。
问题是,每个代码编辑都会分别添加到撤消堆栈中。我想要的是将这个动作作为一个原子单元处理,即按下CTRL + Z回滚所有代码编辑和其他所有内容(当然,加上单位置于重做堆栈之上)。
关于这个主题的文档非常差,我发现的唯一一件事就是IOleParentUndo单元 - 但我没有成功实现它。
我用
IVsTextLines.GetUndoManager()
获取撤消管理器 - 这似乎是一个良好的开端。
答案 0 :(得分:2)
我在代码下面封装了几个动作。
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
}
答案 1 :(得分:1)
如果在文档级别管理撤消,那么您可能必须使用RunningDocumentTable枚举表,获取撤消管理器以及从轨道进行核攻击:
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);
}
}
}
答案 2 :(得分: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;
}