Примите во внимание следующее:
@contextmanager
def ctx():
print('enter ctx')
try:
print('ctx begins yield')
yield
print('ctx finishes yield')
finally:
print('exit ctx')
def gen_nums(n):
print('entering generator')
l = range(n)
with ctx():
print('inside context manager')
for i in l:
print('gen before yield')
yield i
print('gen after yield')
print('existing ctx')
print('exiting generator')
Результат таков: ] последней итерации generator
и до того, как она достигнет StopIteration
. Таким образом, на самой последней итерации generator
contextmanager
оставался бы открытым, если бы он не выполнялся в цикле for (который обрабатывает StopIteration
).
Вы не сможете поймать StopIteration
в contextmanager
, потому что это происходит после , когда generator
исчерпан, и в этот момент contextmanager
уже был бы завершен ,
Кроме того, IIRC, при построении contextmanager
вы всегда должны использовать try... finally...
в любом случае.
Сделайте, чтобы PreferencesDialog реализовал интерфейс, который является одним из свойств команды EditPreference. Команда взаимодействовала бы с диалоговым окном через интерфейс. Для Поблочного тестирования фиктивный объект реализовал бы интерфейс вместо этого.
Диалоговый класс затем может находиться на Вашем самом высоком слое.
Вам будет нужен контроллер в Вашем случае. Контроллер должен ответить за показ предпочтительного диалогового окна.
Поскольку я могу предположить его, контроллер должен быть ответственен за создание ShellModelView и DataContext обязательного представления к нему. Контроллер должен быть также ответственен за обработку казни команды EditPreferences. В логике выполнения контроллер создаст новый PreferencesDialog и его соответствующую модель представления.
Можно найти подобные шаблоны в Призме, если Вы не имеете, уже сделал это. Можно также снова использовать DelegateCommand, обеспеченный там :)
Возможно, это не соответствующий способ посмотреть на него, но это - подход, который я проявляю с M-V-VM в WPF. Вводными окнами и диалоговыми окнами или представлением "EditPreferences" является UI определенные функции. Если я должен был переписать Ваш весь UI, заменяющий все представления, я могу волновать объединение представления "EditPreferences" с другим представлением и поэтому никогда не хотеть открыть его на другом экране. Если бы это было связано с ViewModel, то было бы трудно двигаться. В этой конкретной ситуации у меня были бы кнопка или пункт меню в моем "ShellView", который создает новый экземпляр моего представления "EditPreferences" и затем передает в "EditPreferences" ViewModel, который может или прибыть из свойства в моем "ShellViewModel" или возможно мое представление "EditPreferences" инстанцирует самого ViewModel.
Вот подобный вопрос на том, Так, чтобы в основном сказал то же самое: Вопрос о Дизайне M-V-VM. Вызов Представления от ViewModel
Мои 2 цента:
Передайте какой-то контракт фабрики просмотра в качестве параметра команды или вставьте контракт фабрики просмотра в модель представления. Модель представления будет использовать фабрику представлений для создания любых модальных / немодальных представлений, которые им необходимы. Viewfactory также может принимать в качестве параметра своего метода Show / ShowModal модель представления для отображения. Кроме того, фабрика представлений может использовать табличку с данными для отображения любого модального представления, переданного в качестве параметра.
Добавьте свойство ShowViewModel к рассматриваемой модели представления. Затем DataTrigger может следить за этим свойством и, когда оно относится к определенному типу, отображать представление и т. Д.