Как реализовать операцию 'отмены' в приложении Windows .NET?

Существует и модуль datetime, и класс , и , и класс datetime. Вы пытаетесь вызвать модуль:

import datetime
dt = datetime(2019, 3, 1)  # This will break!

Вместо этого вам нужно либо импортировать класс из модуля:

from datetime import datetime
dt = datetime(2019, 3, 1)  # Okay!

... или импортировать модуль и ссылка на класс:

import datetime
dt = datetime.datetime(2019, 3, 1)  # Good!
11
задан cdiggins 5 January 2010 в 17:17
поделиться

9 ответов

There are a few options. The important thing is that you start designing it in early in the project. Trying to add it to an existing project can be very expensive if it wasn't designed with this capability in mind.

There are a few fundamental patterns that you'll want to take advantage of:

  1. MVC or Observer pattern. The first key isn't so much the religious or pattern-zealot implementation of your high-level architecture. What is important is that your software recognizes the difference between its current state and the displayed state, and decouples appropriately. There needs to be a common, clearly-defined coupling between your visual state and your application state. This provides you with the common architecture you need to create a command (see #2).

  2. The Command pattern. You get a lot of quality with the command pattern (though it can come at the cost of some code that looks like it should be wizard-generated). The specific approach you take to the command pattern may vary (one class per command with implementation via overrides versus one class per many commands with implementation via event handlers, e.g.), but commands are the "action" class that @Ralph suggested structuring a stack around.

    This can be a bit tricky, but the general approach would be to listen for an event that would "commit" data from the visual state to the app state. The Validated event might be a good hook for a Textbox. The Click event would make more sense for a Button. When that commit happens, you create the command associated with that control, you attempt to execute the command, and you add the command to your undo stack if the command completes successfully. Now you're tracking exactly what's happening and exactly the data it's happening with.

  3. The Memento pattern. @JP Pulled out the last piece of the puzzle. You can use a memento on the saved command to store what the affected control's state was before the command executed. This, combined with an UnExecute() member on your command's interface, should be the last core piece of design you need to perform your task.

The nice thing about a structured approach like this is that you now have a natural extension point for additional behavior that needs to happen on a command-basis. Transactions are a natural fit, for example. In my current project, I'm using the WPF ICommand interface (in my winforms project) to provide feedback about whether a given command CanExecute() at any given time. This lets me enable and disable UI widgets appropriately in a purely command-driven way. :)

The unfortunate thing is that there isn't a lot of support for this structure built-in to Winforms (as far as I know), so you'll need to build most of it from scratch. No single piece is particularly complicated, but you can find yourself generating a fair amount of mostly-boilerplate code for each command. It's also a pervasive design technique. For it to be effective, it has to be used consistently throughout the appropriate portions of the application. This makes retrofitting the functionality pretty expensive, especially if the original code is tightly coupled and incohesive.

14
ответ дан 3 December 2019 в 04:33
поделиться

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

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

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

1
ответ дан 3 December 2019 в 04:33
поделиться

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

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

1
ответ дан 3 December 2019 в 04:33
поделиться

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

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

3
ответ дан 3 December 2019 в 04:33
поделиться

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

1
ответ дан 3 December 2019 в 04:33
поделиться

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

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

0
ответ дан 3 December 2019 в 04:33
поделиться

This might not be the best way to go about it depending on what you're trying to accomplish, but you could use a richtextbox and call upon the undo method built into that control.

For example:

richTextBox1.Undo();
2
ответ дан 3 December 2019 в 04:33
поделиться

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

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

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

1
ответ дан 3 December 2019 в 04:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: