You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I have run into a couple situations where I need to run an action after a change is applied, either undoing or redoing. In this case, it's to simply "refresh" a view after a change, because trying to do it step-by-step is too complex. There is no obvious way to do it, but I built my own UndoBatch class that seems to work well.
What do you think? Should I send it as a pull request, possibly replacing the existing UndoBatch? Is there a preferred way?
Here it is:
public class UndoBatchWithAction : IDisposable
{
public UndoBatchWithAction(ISupportsUndo instance, string description, bool consolidateChangesForSameInstance, Action preChangeAction = null, Action postChangeAction = null)
: this(UndoService.Current[instance.GetUndoRoot()], description, consolidateChangesForSameInstance, preChangeAction, postChangeAction)
{
}
public UndoBatchWithAction(UndoRoot root, string description, bool consolidateChangesForSameInstance, Action preChangeAction = null, Action postChangeAction = null)
{
if (this.PreChangeAction != null)
this.PreChangeAction();
if (null == root)
return;
_UndoRoot = root;
this.PreChangeAction = preChangeAction;
this.PostChangeAction = postChangeAction;
this.AddInitialAction();
root.BeginChangeSetBatch(description, consolidateChangesForSameInstance);
}
private UndoRoot _UndoRoot;
private Action PostChangeAction;
private Action PreChangeAction;
private void AddInitialAction()
{
object target = null;
var changeToRebindUponUndo = new DelegateChange(target,
this.PostChangeAction,
this.PreChangeAction,
new Tuple<object, string>(target, "Initial action"));
this._UndoRoot.AddChange(changeToRebindUponUndo, "Act before changeset is applied.");
}
private void AddFinalAction()
{
object target = null;
var changeToRebindUponRedo = new DelegateChange(target,
this.PreChangeAction,
this.PostChangeAction,
new Tuple<object, string>(target, "Final action."));
this._UndoRoot.AddChange(changeToRebindUponRedo, "Act after changeset is applied.");
}
#region IDisposable Members
private void Dispose(bool disposing)
{
if (disposing)
{
if (null != _UndoRoot)
{
this.AddFinalAction();
_UndoRoot.EndChangeSetBatch();
}
if (this.PostChangeAction != null)
this.PostChangeAction();
}
}
/// <summary>
/// Disposing this instance will end the associated Undo batch.
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
}
I have two thoughts, but maybe these don't meet your exact scenario...
1 - UndoRoot has two events on it that should fire any time an undo or a redo happen. If you hook these events, you could do the refresh as a response.
2 - The Change class will inspect the "target" of the undo to see if it implements ISupportUndoNotification. If so, it'll call UndoHappened or RedoHappened after applying the changes to that object.
I suspect that your "refresh" needs to touch something outside your objects that are being undone. If so, then the UndoRoot might be the best option. Does this make sense and/or meet your goals? If not, can you help me understand more about your scenario?
Thanks,
Nathan
ses4j wrote Feb 22, 2014 at 6:12 PM [x]
If I understand correctly, neither of those hooks are convenient for me because I don't want it to happen on ALL undos or even all undos to a particular class. It's really just one particular change section.
In my case, that change is about radically resetting the data context of a WPF data grid on a file load-type operation. I want the whole load batched into a single undo operation, and I want the grid to rebind after the entire change occurs (or de-occurs).
Thanks for the reply!
Scott
nallenwagner wrote Feb 22, 2014 at 9:32 PM [x]
Thanks @ses4j. That makes sense.
I think what you've put together here looks like a great solution. Thanks for sharing it. I'll see what I can do to include it in future releases of the library, if you'd like.
Nathan
ses4j wrote Feb 22, 2014 at 10:03 PM [x]
Sure. Like I said, happy to make a pull request if you want. Would you prefer it as simply a patch to UndoBatch with additional optional arguments, or as a new standalone class?
The text was updated successfully, but these errors were encountered:
(Submitted by ses4j on Codeplex)
I have run into a couple situations where I need to run an action after a change is applied, either undoing or redoing. In this case, it's to simply "refresh" a view after a change, because trying to do it step-by-step is too complex. There is no obvious way to do it, but I built my own UndoBatch class that seems to work well.
What do you think? Should I send it as a pull request, possibly replacing the existing UndoBatch? Is there a preferred way?
Here it is:
Hi @ses4j,
Thanks for the suggestion here.
I have two thoughts, but maybe these don't meet your exact scenario...
1 - UndoRoot has two events on it that should fire any time an undo or a redo happen. If you hook these events, you could do the refresh as a response.
2 - The Change class will inspect the "target" of the undo to see if it implements ISupportUndoNotification. If so, it'll call UndoHappened or RedoHappened after applying the changes to that object.
I suspect that your "refresh" needs to touch something outside your objects that are being undone. If so, then the UndoRoot might be the best option. Does this make sense and/or meet your goals? If not, can you help me understand more about your scenario?
Thanks,
Nathan
ses4j wrote Feb 22, 2014 at 6:12 PM [x]
If I understand correctly, neither of those hooks are convenient for me because I don't want it to happen on ALL undos or even all undos to a particular class. It's really just one particular change section.
In my case, that change is about radically resetting the data context of a WPF data grid on a file load-type operation. I want the whole load batched into a single undo operation, and I want the grid to rebind after the entire change occurs (or de-occurs).
Thanks for the reply!
Scott
nallenwagner wrote Feb 22, 2014 at 9:32 PM [x]
Thanks @ses4j. That makes sense.
I think what you've put together here looks like a great solution. Thanks for sharing it. I'll see what I can do to include it in future releases of the library, if you'd like.
Nathan
ses4j wrote Feb 22, 2014 at 10:03 PM [x]
Sure. Like I said, happy to make a pull request if you want. Would you prefer it as simply a patch to UndoBatch with additional optional arguments, or as a new standalone class?
The text was updated successfully, but these errors were encountered: