Отслеживание параметров с помощью шаблона команд и ICommand для отмены / возврата. Хранение нескольких команд?

Я работал над приложением WPF, которое включает перемещение множества фигур. Это в основном MVVM и сильно зависит от команд. До недавнего времени я не беспокоился об Undo / Redo. Я не думаю, что это будет слишком сложно, поскольку большинство моих изменений связаны с командами, которые наследуют базовый класс CommandBase, реализующий ICommand.

Пока что я добавил еще один интерфейс с именем IUndoCommand, который использует ICommand. Я добавил метод отмены, который будет выполнять операции, необходимые при вызове отмены.

Я буду использовать стек как для Undo, так и для Redo, но у меня возникла проблема с параметрами для методов Execute / Undo. Есть ли правильный способ сохранить эти параметры объекта типа? Целесообразно ли добавлять поле / метод в IUndoCommand? Если да, я должен установить его в методе Execute или в конструкторе (если я вообще могу).

Если нет, я должен передать его как собственный объект в стеке?

Во-вторых, (хотя, вероятно, это может быть ваш собственный вопрос) есть ли лучшая структура данных для отслеживания нескольких команд? В настоящее время у меня есть цикл, который запускает несколько команд для перемещения нескольких выбранных фигур, и я хотел бы разрешить одну отмену, чтобы отменить их все. Думаю, я мог бы преобразовать это в команду самостоятельно и передавать ей команды, но опять же, я новичок в этом и предпочел бы сделать это правильно.

Спасибо за чтение, и любая помощь будет принята с благодарностью.

Источники:

Проект кода VisualStudioMagazine StackOverFlow


person Michael Clausing    schedule 01.02.2013    source источник
comment
Вы смотрели на шаблон дизайна Momento? Это специально для отмены. Повторить будет как раз наоборот, как в случае с очередями. en.wikipedia.org/wiki/Memento_pattern   -  person SASS_Shooter    schedule 01.02.2013
comment
Я это видел, и это то, над чем я изначально начал работать. Я чувствую, что это дает мне больше контроля и лучше работает с тем, что я уже сделал. У меня есть DrawingEditViewModel, который установлен как мой текст данных. Это наблюдаемые коллекции моделей просмотра, которые взаимодействуют с моделями. Он также отслеживает ширину / высоту моего контента и расстояние (поскольку есть масштабирование). Есть вероятность, что я мог бы переместить ширину / высоту / масштабирование в другой класс, но ему все равно потребуется доступ к нему.   -  person Michael Clausing    schedule 01.02.2013
comment
Это проблема, поскольку самое простое решение в шаблоне проектирования momento - правильная глубокая копия всей модели представления? Это приведет к тому, что изменения увеличения / уменьшения будут сохранены как шаг, который будет довольно раздражающим. Пользователь должен 8 раз нажать + z, чтобы вернуться в свою последнюю позицию просмотра. Я надеюсь в этом есть смысл..   -  person Michael Clausing    schedule 02.02.2013


Ответы (1)


Поскольку интерфейсу не нужен доступ к данным (ему просто нужна пара методов _1 _ / _ 2_ и, возможно, флаг, указывающий, может ли он отменить), ему вообще не нужно знать о параметрах.

Один из вариантов может заключаться в том, чтобы сделать вашу реализацию IUndoCommand универсальной. Затем вы можете использовать это, чтобы сохранить параметр безопасным для типов способом.

Тогда ваш CommandBase класс может быть общим, то есть:

class CommandBase<T> : ICommand, IUndoCommand
{
    // You could then store the parameter directly...
    public T Parameter { get; private set; }
}
person Reed Copsey    schedule 01.02.2013
comment
Понятно, мне нравится это решение, но можно ли установить его в методе Execute? Я так думаю, потому что команда не будет добавлена ​​ни в один стек, если не будет вызван Execute. Я просто не уверен, что нет лучшего способа ... - person Michael Clausing; 02.02.2013