Я новичок в MVVM и IoC.Я использую ViewModel-первый подход для этого проекта.Моя организация сборок проекта выглядит следующим образом:
View
(имеет ссылку на ViewModel
)
ViewModel
(имеет ссылку на Model
)
Model
Поначалу работал нормально, пока мне не нужно представление Login
.Login
запускать при запуске программы.При успешном входе в систему будет отображаться MainWindow
, а Login
должен сам закрыться.Обратное можно сделать с помощью LogoutCommand
из MainWindow
.
Основным препятствием, с которым я сталкиваюсь, является создание View
(Окна) для данного типа ViewModel
, в то время как ViewModel
не знает о View
.В поисках ответа я нашел:
- Шаблон Посредник / Посланник.Что мне показалось очень удобным, я использовал этот шаблон для отображения диалога
MessageBox
.Но только для этой цели мне неудобно использовать этот шаблон для обработки объектов. - Внедрение зависимостей.Новая концепция для меня.Но я вижу реальную выгоду отделения знаний конструктора сервиса от потребительского класса.Поэтому я попробовал MVVM-Light
SimpleIoc
для начала, введя View
экземпляр в ViewModel
конструктор в качестве интерфейса и продолжил регистрировать их на ViewModelLocator
SimpleIoc.Default.Register<IMainWindowView, MainWindow>();
SimpleIoc.Default.Register<ILoginView, Login>();
SimpleIoc.Default.Register<LoginVM>();
SimpleIoc.Default.Register<MainWindowVM>();
При успешном входе в системуMainWindow
показано и Login
закрыто.Но когда я вышел из системы MainWindow
, чтобы снова показать Login
, я столкнулся с InvalidOperationException Cannot set Visibility or call Show, ShowDialog, or WindowInteropHelper.EnsureHandle after a Window has closed.
Поэтому я подумал, что мне нужно "очистить" экземпляр, созданный SimpleIoC
, отменив его регистрацию в событии закрытия окна.
public class ViewModelBaseEx : ViewModelBase
{
protected SimpleIoc Ioc
{
get { return SimpleIoc.Default; }
}
protected virtual void Unregister<T>() where T : class
{
Cleanup();
if (Ioc.IsRegistered<T>())
{
// Attempt to remove instance
Ioc.Unregister<T>();
// If i still need to show this window again,
// shouldn't i need to have this instance available? (not sure)
Ioc.Register<T>();
}
}
}
Увы, описанный выше обходной путь не сработал, и теперь я не знаю, что делать.
- Каковы достоинства / недостатки моего подхода?
- Какобрабатывать динамический экземпляр с контейнером IoC?
ОБНОВЛЕНИЕ
Регистрация после отмены регистрации кажется необходимой, так как тип не может быть найден, если оставить его только незарегистрированным.Что касается проблемы, кажется, мне также нужно отменить регистрацию типа View
.Поэтому я добавляю немного кода в View
(Окно)
private void MainWindow_Closed(object sender, EventArgs e)
{
SimpleIoc.Default.Unregister<IMainWindowView>();
SimpleIoc.Default.Register<IMainWindowView, MainWindow>();
}
Пока все отлично работает, приемлем ли этот подход?