简体   繁体   中英

Orc.Memento Global Undo with Multiple Controls

I have a need to implement a memento undo-redo pattern. My application has multiple tabs and in these tabs there are multiple controls which all implement Orc.Memento. The trouble I am having is calling undo with the menu button on MainWindow and in the button action call undo on the last active control.

Edit: this project is unfortunately does not follow MVVM.

I chose Orc.Memento because it is super easy to implement without modifying objects. What I have now is working great only with keyboard commands Ctrl+X & Ctrl+Y. Calling undo only does undo on the active control. However, when I click the undo/redo buttons on the MainWindow menu my code does not know the last active control to call undo/redo on.

Option 1

Option one is to keep track of the last active control by setting a global property on GotFocus() of each control. I feel like there has to be a better way.

Option 2

That is why I am here :-).


Control

public class MyControl : IMemento
{
    private MementoService mementoService = new MementoService();

    public void RegisterAll()
    {
        mementoService.RegisterObject(myObject);
        mementoService.RegisterCollection(myCollection);
    }

    public void Undo()
    {
        mementoService.Undo();
    }

    public void Redo()
    {
        mementoService.Redo();
    }
}

MainWindow

Ctrl+Z & Ctrl+Y is mapped here. The undo/redo methods find the currently active control and call undo/redo at that control.

public MainWindow
{   
    /// <summary>
    /// Call undo on the currently active control
    /// </summary>
    public void Undo()
    {
        /*
         * get current focused control.
         * find the parent that is an IMemento. And call Redo on that control
         */
        var focusedControl = FocusManager.GetFocusedElement(this);
        var mementoControl = UIHelper.TryFindParentThatIsIMemento<Control>(focusedControl as DependencyObject);

        /*
         * Call Undo on the control that is currently active
        */
        if (mementoControl != null && mementoControl is IMemento)
        {
            var mem = (mementoControl as IMemento);
            mem.Undo();
        }
    }
}

Note: If I could program this how Excel works by auto navigating to the control where the undo/redo happens that would be great. It is not necessary, but if you have an idea my ears are open.

Here are a few recommendations:

  1. Try to implement undo/redo against models (eg using Orc.ProjectManagement), not against views (since views are short-living

  2. Try to use the TabControl from Orc.Controls, which allows you to keep all the tabs active and thus allowable for redo/undo).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM