Как реализовать операцию отмены в приложении Windows .net? - PullRequest
11 голосов
/ 29 апреля 2009

Предположим, что выигрышная форма имеет определенные поля ввода, и пользователь вводит / повторно вводит некоторые данные.

Как сохранить данные, ранее введенные операцией отмены?

Просто я хочу знать, как лучше всего это сделать.

Ответы [ 9 ]

14 голосов
/ 29 апреля 2009

Есть несколько вариантов. Важно то, что вы начинаете разрабатывать его в самом начале проекта. Попытка добавить его в существующий проект может стоить очень , если он не был разработан с учетом этой возможности.

Есть несколько фундаментальных шаблонов, которыми вы захотите воспользоваться:

  1. MVC или Наблюдатель шаблон. Первый ключ - это не столько религиозная или шаблонная реализация вашей архитектуры высокого уровня. Что важно для , так это то, что ваше программное обеспечение распознает разницу между его текущим состоянием и отображаемым состоянием и соответствующим образом отсоединяется. Должна быть общая, четко определенная связь между вашим визуальным состоянием и состоянием вашего приложения. Это дает вам общую архитектуру, необходимую для создания команды (см. # 2).

  2. Шаблон Command . Вы получаете много качества с помощью командного шаблона (хотя он может стоить некоторого кода, который выглядит так, как будто он генерируется мастером). Конкретный подход к шаблону команды может варьироваться (один класс на команду с реализацией через переопределения по сравнению с одним классом для многих команд с реализацией через обработчики событий, например), но команды - это класс «действия», который @Ralph предложил структурировать стек вокруг.

    Это может быть немного сложнее, но общий подход заключается в прослушивании события, которое "фиксирует" данные из визуального состояния в состояние приложения. Событие Validated может быть хорошим хуком для Textbox. Событие Click будет иметь больше смысла для Button. Когда происходит фиксация, вы создаете команду, связанную с этим элементом управления, пытаетесь выполнить команду и добавляете команду в свой стек отмены, если команда завершается успешно. Теперь вы точно отслеживаете, что происходит, и данные, с которыми оно происходит.

  3. Шаблон Memento . @JP вытащил последний кусок головоломки. Вы можете использовать сувенир в сохраненной команде, чтобы сохранить состояние уязвимого элемента управления до выполнения команды. Это, в сочетании с элементом UnExecute() в интерфейсе вашей команды, должно быть последним основным элементом дизайна, который вам нужен для выполнения вашей задачи.

Хорошая вещь в таком структурированном подходе состоит в том, что теперь у вас есть естественная точка расширения для дополнительного поведения, которое должно происходить на командной основе. Например, транзакции естественны. В моем текущем проекте я использую интерфейс WPF ICommand (в моем проекте winforms), чтобы обеспечить обратную связь о том, является ли данная команда CanExecute() в любой момент времени. Это позволяет мне включать и отключать виджеты пользовательского интерфейса надлежащим образом, исключительно на основе команд. :)

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

3 голосов
/ 29 апреля 2009

Я не уверен, что в WinForms / .Net есть какая-то встроенная функция отмены, которой вы можете воспользоваться. Но то, что вы действительно ищете, - это структура данных стека, которая поможет вам управлять списком действий. Вам нужно будет создать некоторый тип объекта «action» для представления действий, которые может выполнять пользователь, и по мере прохождения приложения вам нужно будет перенести эти действия в стек. Когда они нажимают кнопку отмены, или Ctrl-Z, или любой другой способ инициирования действия отмены, вы отключаете текущее действие и восстанавливаете состояние приложения к предыдущему действию.

Это очень простой и общий обзор того, как это будет работать, но я думаю, что реализация такой функции может быть довольно сложной. Только представьте, как это должно работать для такой программы, как Adobe Photoshop. : O

2 голосов
/ 29 апреля 2009

В зависимости от того, чего вы пытаетесь достичь, это может быть не лучшим способом, но вы можете использовать richtextbox и вызывать метод отмены, встроенный в этот элемент управления.

Например:

richTextBox1.Undo();
1 голос
1 голос
/ 14 мая 2009

Вы также можете найти библиотеку Реверси полезной, как, кажется, и некоторые другие. См. [http://www.codeproject.com/KB/dotnet/reversibleundoredo.aspx][1] или [это] [2]

[1]: http://www.codeproject.com/KB/dotnet/reversibleundoredo.aspx Сделать ваше приложение обратимым для поддержки отмен и повторов

[2]: http://www.codeproject.com/script/Articles/Article.aspx?aid=22502 Отменить повтор

1 голос
/ 29 апреля 2009

Мое предложение состоит в том, чтобы определить конкретные требования отмены и их практические преимущества перед началом проектирования и реализации. Я унаследовал приложение WinForms, которое использовало последовательную отмену нескольких операций через стек общих объектов «действие» внутри. Однако оказалось, что никто из пользователей приложения, с которыми я общался, не пользовался и не запрашивал эту функцию! И как работает это конкретное приложение, если бы я был пользователем приложения, я бы просто не увидел себя использующим эту функцию.

Функциональность отмены могла бы быть более полезной в этом случае, если бы она была «выборочной» отменой; где пользователь может выбрать любую отдельную операцию / редактирование нескольких предыдущих изменений, выполненных до фиксации данных, и восстановить это одиночное редактирование в исходное состояние, вместо того чтобы иметь возможность только отменить последнюю операцию сначала, а затем вторую операцию до последней и т. д., как это было реализовано.

В любом случае, приложение, таким образом, содержит ненужную сложность и косвенность, что усложняет и замедляет процесс «взлома» и внесения изменений и улучшений в существующую функциональность, в данном случае практически без выгоды для реального мира. С тех пор как я унаследовал проект, я реализовал новые функции без отмены, и никто не жаловался.

1 голос
/ 29 апреля 2009

CTRL + Z работает на отдельных элементах управления.

Если вы работаете с данными и BindingSource, вы можете "отменить" несохраненные изменения в записи (записях), вызвав функцию CancelEdit или, в качестве альтернативы, вы можете перезагрузить данные для базы данных.

1 голос
/ 29 апреля 2009

Это и это может помочь.

0 голосов
/ 29 апреля 2009

Зависит от того, сколько уровней отмены вы хотите иметь.

Вы можете сохранить значения до того, как они в некотором смысле будут «зафиксированы», в коллекцию на уровне формы для каждого из элементов управления, которую можно «восстановить» по нажатию кнопки, чтобы пользователь мог вернуться.

...