2012-02-09 4 views
1

У меня есть архитектурная проблема и возможное решение, для которого я хотел бы получить мнение.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 все еще жива в стопке но загруженные/разгруженные, если они видны, прикреплены/отсоединены к визуальному дереву).

Будет оценено любое другое мнение (даже конферентное).

Спасибо

ответ

1

Что вы думаете о том, время жизни ViewModel быть таким же, как своего мнения (это всегда упрощенное мое приложение до сих пор)?

Это звучит разумно для меня, так как оно напрямую связано с DataContext.

Что вы думаете о NavigateTo-NavigateFrom ViewModel знаете решение ?

Я не думаю, что это хорошая идея. В шаблоне MVVM ViewModels не должны ничего знать о представлении. Навигация обычно связан с представлениями, поэтому я не думаю, что это лучшая идея.

Что вы думаете о представлении View-Finalization ViewModel, известном как ?

Не говоря уже о завершении, метод очистки для моделей с обзором - это ИМО путь. В базовом классе для всех ваших ViewModels (я надеюсь, что у вас есть), можно поставить следующий метод:

public abstract class ViewModelBase 
{ 
    .... 
    public virtual void Cleanup(); 
} 

Затем просто позвонить myViewModel.CleanUp();, когда ваш взгляд закрыт. Отмените ваши события в конкретной реализации CleanUp:

public override void CleanUp() 
{ 
    ....Event -= this....EventHandler; 
} 
+0

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

+0

Я также обнаружил, что финализация не будет работать, потому что это может произойти в конце будущего. Виртуальная очистка в viewmodelbase - лучшее решение (так что представление будет знать только о базе). Я должен выяснить, когда самое лучшее время для этого. Вероятно, в большинстве случаев событие Unloaded является одним (помня, что оно называется все время, когда представление отделяется от визуального дерева, но представление может продолжать существовать в стопке). В таком случае регистрация событий должна произойти в загруженном событии, поэтому мне нужно будет добавить метод Initialize в базу viewmodel. – SkyG

1

Я согласен, что слабая идея события хорошо, но это было бы слишком громоздкими для реализации. Он также создает собственные проблемы - он может сделать viewmodel полностью слабой ссылкой, что делает его кандидатом на сбор мусора, прежде чем он на самом деле «должен» (мнение разработчика и мнение коллекционера мусора). Я был укушен этим раньше, как и Уорд Белл в этом blog post of his.

Основываясь на ваших требованиях и желании следовать «чистым» подходам к MVVM (viewmodel не знает о представлении), кажется, что вы боретесь с балансом между «представлением» и «моделью» viewmodel. В этом случае я бы предложил другой шаблон проектирования: MVPVM (model/view/presenter/viewmodel). Вот на нем MSDN article.

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

Мне нравится подход MVPVM, потому что он всегда меня интересовал в MVVM, когда мои режимы просмотра стали брать на себя слишком большую ответственность (разговаривая с уровнем доступа к данным, слушая общесистемные события, а также обрабатывая команды из представления, поддерживая его свойства для представления и т. д.). Я знаю, что это не обязательно ответ на ваш вопрос, но слишком длинный комментарий.

Смежные вопросы