У меня есть архитектурная проблема и возможное решение, для которого я хотел бы получить мнение.ViewModel Регистрация событий и ViewModel Lifetime
Я использую архитектуру MVVM для WP7 (по возможности, но, к сожалению, иногда sdk, похоже, идет в противоположном направлении).
WP7 принудительно использует подход ViewFirst, и я чувствую себя комфортно с этим (за исключением той части, которую мы не можем переопределить для создания вида, как в Silverlight, для возможности впрыска конструктора). Я убедился в том, что большую часть модели просмотра следует за личным временем ее просмотра. Таким образом, viewmodel создается, когда создается представление (путем доступа к ViewModelLocator), ViewModel (или должен) ссылаться только на его представление, когда представление уничтожается, и его ViewModel должен быть уничтожен (его не обязательно, но его способ я иду, за исключением очень редкого случая, для которого я создаю одномодовый viewmodel).
Моей viewmodel может потребоваться зарегистрировать на некоторых событиях службы однопользовательского режима (сотовой или однояйцовый класс i). Я имею в виду, что ему может потребоваться зарегистрироваться в случае класса, срок жизни которого не определяется самой viewmodel. Эти события сохраняют жесткую привязку к моей модели viewmodel и сохраняют мою модель просмотра живыми даже тогда, когда представление разрушено, и не только моя модель просмотра будет продолжать получать и обрабатывать события. Шаблон WeakEvent может быть возможным решением, но невозможно создать eventmanager для каждого события. Лучшее решение, на мой взгляд, не существует и должно быть ключевым словом для слабой регистрации событий.
Решение, которое я нашел, - это показать, что моя модель просмотра знает NavigateTo и NavigateFrom, поэтому я могу регистрировать и отменить регистрацию событий. Я также могу добавить некоторую логику (например, я мог бы отменить регистрацию только в случае обратной), обращая внимание на зеркальную логику в NavigateTo и NavigateFrom.
Еще один возможный способ (я не проверял) мог бы сделать мою модель просмотра осведомленной о завершении просмотра и выполнить некоторую очистку, когда представление будет завершено, но у меня всегда было ощущение, что этот подход не рекомендуется, поскольку он запрещает использование финализации. Также мне непонятно, насколько повлияет производительность.
Что вы думаете о том, что срок службы viewmodel будет таким же, как и его вид (он всегда упрощал мое приложение до сих пор)? Что вы думаете о решении NavigateTo-NavigateFrom ViewModel? Что вы думаете о решении View-Finalization ViewModel? Испытывали ли вы какое-либо из этих или, возможно, другое решение?
С уважением SkyG
UPDATE
Я обнаружил, что решение финализации не будет делать работу beacuse это не может произойти в конце будущего (или, возможно, никогда). На данный момент мне кажется, что лучшим решением является пара виртуального метода в viewmodelbase Initialize и Cleanup для регистрации регистрации событий, которую должен вызвать вызов. Возможный момент их вызова может быть во время загруженного и разгруженного события (когда мне не нужен мой режим viewmodel, если я нахожусь в следующем представлении, в этом случае первая модель view/viewmole все еще жива в стопке но загруженные/разгруженные, если они видны, прикреплены/отсоединены к визуальному дереву).
Будет оценено любое другое мнение (даже конферентное).
Спасибо
Я согласен с тем, что ViewModel не должен быть viewaware, но я предполагаю, что они не должны быть конкретными viewaware. Я могу заставить ViewModel знать навигацию, зная о представлении (например, с посланником). Есть ли какая-либо другая техническая причина, по которой вам не нравится этот метод?для очистки это звучит неплохо, единственная проблема - когда звонить и от нее, я могу думать только, чтобы назвать ее во время навигации, из которой все еще то же самое, что и выше или во время финализации, есть ли у вас какая-либо другая идея? – SkyG
Я также обнаружил, что финализация не будет работать, потому что это может произойти в конце будущего. Виртуальная очистка в viewmodelbase - лучшее решение (так что представление будет знать только о базе). Я должен выяснить, когда самое лучшее время для этого. Вероятно, в большинстве случаев событие Unloaded является одним (помня, что оно называется все время, когда представление отделяется от визуального дерева, но представление может продолжать существовать в стопке). В таком случае регистрация событий должна произойти в загруженном событии, поэтому мне нужно будет добавить метод Initialize в базу viewmodel. – SkyG