2017-01-21 6 views
2

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

+0

Возможно, вы захотите посмотреть мое недавнее видео по работе с диалогами в MVVM (https://www.youtube.com/watch?v=OqKaV4d4PXg). Это обычная проблема, но ее можно решить относительно легко. Вам все равно нужно решить, как вы хотите внедрять службы (или нет), потому что вы также можете использовать шаблон локатора службы или другие методы. Инъекция - не единственный способ. –

ответ

1

Почему инъекционный класс, реализующий IDialogService, в режимах просмотра IoC? Я думаю, что это хороший способ сделать это.

Не переусердствуйте, разделяя взгляды и логические проекты - хорошая идея, просто используйте все, что работает для вас.

В моем последнем проекте я использовал класс взаимодействия из инфраструктуры ReactiveUI. Он хорошо работает с диалогами и сборщиками файлов. Я думаю, что это очень похоже на вашу альтернативу, вы можете проверить code и examples.

Он использует реактивные расширения, но вы должны получить эту идею.

+0

Учитывая ссылочную структуру, я не могу сделать интерфейс 'IDialogService' известным в моих моделях просмотра, не помещая его туда или в какой-то общий/общий проект. Но реализация этого интерфейса будет * иметь * в проекте UI, потому что он показывает окно. Это просто не кажется мне «правильным», а скорее как способ обойти недостающую ссылку на проект. Я посмотрю ссылки, которые вы предоставили завтра, спасибо! – InvisiblePanda

+0

Почему бы не просто поместить интерфейс IDialogService в проект viewmodels? Ваши модели просмотра должны быть доступны для запуска программы с (вне) любого пользовательского интерфейса, поэтому его естественно поместить. Конечно, реализация должна быть в проекте пользовательского интерфейса, это точка разделения - удаление зависимости от пользовательского интерфейса из режимов просмотра и предоставление интерфейса для взаимодействия с пользовательским интерфейсом. –

+0

Вы убеждаете меня, по пунктам;) Мне все еще кажется «странным», чтобы зарегистрировать реализацию из проекта пользовательского интерфейса с интерфейсом из UI.ViewModels, но, с другой стороны, это также кажется правильным ... Я могу также по-прежнему создают новые экземпляры модели представления из виртуальной машины, передавая «IDialogService» виртуальную машину верхнего уровня, полученную изначально. У вас есть мнение об этой идее? – InvisiblePanda

1

В моем сценарии это не работает, поскольку DialogService должен быть в проекте пользовательского интерфейса, но я должен назвать его из модели представления.

Интерфейс IDialogService должны быть определены в виде модели проекта. Модели просмотра только знают об этом интерфейсе, и вы можете легко обеспечить их макетную реализацию в своих модульных тестах, которые просто возвращают bool?, фактически не создавая диалог.

Конкретная реализация IDialogService, то есть класса DialogService, который создает окно, с другой стороны должна быть реализована в проекте пользовательского интерфейса.

Я мог бы, конечно, злоупотреблять DI/IoC, чтобы внедрить реализацию IDialogService в мои модели просмотра, но это не то, что я хочу сделать.

Это не злоупотребление образцом инъекции влагалища. Это довольно типичное и правильное использование этого. Я использую его сам, и он творит чудеса.

Ваше альтернативное решение по расширению базового класса модели представления для обеспечения какой-либо функциональности диалога кажется мне грязным и неправильным. Я бы, конечно, придерживался инъецирования интерфейса IDialogService во все модели представлений, которые на самом деле требуют службы диалога. Это то же самое, что вводить их любой другой услугой.

+1

Спасибо, чем больше я думал об этом сегодня, тем больше он прояснялся! И да, мне очень нравится насмехаться над работой. Единственная «проблема», которую я все еще видел (см. Мой второй комментарий выше), заключалась в том, как создавать новые экземпляры виртуальной машины в другой виртуальной машине. Но поскольку в моделях представления уже есть объекты IDialogService, они могут просто передать их. – InvisiblePanda

+0

Да, точно :) – mm8

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

  • Нет связанных вопросов^_^