Диалоги открытия, придерживающиеся шаблона MVVM, как представляется, являются одним из регулярных вопросов (здесь и в другом месте). Я знаю, что есть такие фреймворки, как MVVM light, у которых есть ответы на эту проблему, но сейчас я работаю над небольшим личным проектом, в котором я сам стараюсь делать большую часть материала для учебных целей.Отдельный проект для просмотра моделей для «принудительного» MVVM: как открыть диалоги?
Чтобы «заставить» обратить внимание на ссылки, я решил извлечь модели представления из проекта пользовательского интерфейса и поместить их в отдельную сборку. Проект UI ссылается на UI.ViewModels, но не наоборот. Это привело к возникновению проблем с открытием (модальными) диалоговыми окнами.
Многие люди, кажется, с помощью DialogService
, который делает что-то вдоль линий:
internal class DialogService : IDialogService
{
public bool? OpenDialog(ViewModelBase vm)
{
Window window = new Window();
window.Content = vm;
return window.ShowDialog();
}
}
Соответствующее содержимое окна можно вывести из типа вид модели с использованием DataTemplate
.
В моем сценарии это не работает, так как DialogService
должен быть в проекте пользовательского интерфейса, но я должен назвать его из модели представления. Я мог бы, конечно, злоупотреблять DI/IoC, чтобы внедрить реализацию IDialogService
в мои модели просмотра, но это не то, что я хочу сделать.
Есть ли какой-либо строгий способ заставить это работать?
В качестве альтернативы, я добавил следующий код на ViewModelBase
:
public abstract class ViewModelBase : INotifyPropertyChanged
{
...
public event Action<ViewModelBase, Action<bool?>> Navigate;
protected virtual void OnNavigate(ViewModelBase vm, Action<bool?> callback)
{
Navigate?.Invoke(vm, callback);
}
}
Очевидно, что может быть больше перегрузки, другие параметры, EventArgs
и так далее; и я должен, вероятно, поместить это в интерфейс. Но это всего лишь «мысль».
При создании экземпляра представления (либо с помощью разрешения, либо, например, в NavigationService
, см. Ниже), я могу позволить подписаться на это событие и вызвать обратный вызов NavigationService
. Является ли это проблематичной/плохой идеей? Каковы минусы этого? До сих пор (без тестирования много), мне не нравится то, что я не могу продолжить в следующей строке после открытия диалога, но должен продолжить внутри кода обратного вызова. Это также затрудняет отслеживание потока программы, читая код.
Любой вход очень ценится! Это очень интересная тема, и поскольку многие ответы на эти вопросы о SO довольно датированы, я надеюсь узнать больше о существующих лучших практиках :)
Возможно, вы захотите посмотреть мое недавнее видео по работе с диалогами в MVVM (https://www.youtube.com/watch?v=OqKaV4d4PXg). Это обычная проблема, но ее можно решить относительно легко. Вам все равно нужно решить, как вы хотите внедрять службы (или нет), потому что вы также можете использовать шаблон локатора службы или другие методы. Инъекция - не единственный способ. –