Стандартный подход запуска диалогов / дочерних окон из приложения WPF с помощью MVVM

все, я хотел бы знать признанный лучший подход/отраслевой стандарт запуска [дочерних] диалогов/окон из WPF с использованием шаблона MVVM. Я наткнулся на следующие статьи:

А. CodeProject - отображение диалогов при использовании шаблона MVVM

этот подход кажется мне хорошим, но чрезмерным. Это некоторая степень репликации кода, и я не уверен, что это правильный путь.

Б. WPF MVVM и показ Диалоги

Это кратко проходит через три варианта с различными ссылками, которые все довольно/очень плохо объясняют методологию или имеют-тему.

может кто-нибудь, пожалуйста, предоставить объяснение стандартные промышленности метод / подход запуска диалогов из приложения WPF с использованием MVVM и предпочтительно некоторых ссылок на дальнейший материал для чтения? Если вы сами можете привести пример, я, конечно, буду самым благодарен!

Спасибо за ваше время.

6 ответов


прежде всего, я не знаю никакого "отраслевого стандарта" для отображения диалогов с использованием MVVM, потому что такой вещи нет.
Во-вторых, Добро пожаловать в MVVM, вы только что коснулись областей, для которых MVVM не имеет стандарта.
По правде говоря, MVVM имеет много болевых точек, и именно по этой причине существует множество фреймворков MVVM, чтобы упомянуть несколько MVVM Light, PRISM, Caliburn.Micro, Cinch, Catel, WAF, Baboon, shell я останавливаюсь или вы хотите больше.
Сейчас чтобы ответить на ваш вопрос и после работы с большинством этих фреймворков, я заметил одну общность, все они используют контейнер DI/IoC, а затем предоставляют вам интерфейс, что-то вроде IDialogManager и собственную реализацию, а затем просят вас принять этот интерфейс в вашей модели представления и использовать его для отображения диалогов. Итак, чтобы подвести итог, я бы использовал инъекцию зависимостей, имел интерфейс для отображения диалогов, а затем предоставил и реализовал это и зарегистрировал его в di контейнер, а затем потребляет его из модели или представлений моего представления.
Edit: Итак, вы выбрали PRISM (на мой взгляд) труднее всего между ними всеми в отображении диалогов. Теперь это в стороне, есть трудный путь, который заключается в использовании Запросы На Взаимодействие (проверьте середину статьи), или вы можете использовать этот ответ как более быстрый способ.


недавно я реализовал свой собственный навигационный сервис для WPF, который использует Caliburn.WindowManager Micro (но вы можете заменить его чем-то другим).

пример (как использовать):

_navigationService.GetWindow<ClientDetailsViewModel>()
            .WithParam(vm => vm.IsEditing, true)
            .WithParam(vm => vm.Client, SelectedClient)
            .DoIfSuccess(() => RefreshSelectedClient())
            .ShowWindowModal();

реализация:

namespace ClientApplication.Utilities
{
    public class NavigationService : INavigationService
    {
        SimpleContainer _container;
        IWindowManager _windowManager;

        public NavigationService(SimpleContainer container, IWindowManager windowManager)
        {
            _container = container;
            _windowManager = windowManager;
        }

        public INavigationService<TViewModel> GetWindow<TViewModel>()
        {
            return new NavigationService<TViewModel>(_windowManager, (TViewModel)_container.GetInstance(typeof(TViewModel), null));
        }
    }




    public class NavigationService<TVM> : INavigationService<TVM>
    {
        IWindowManager _windowManager;
        TVM _viewModel;
        System.Action _action;

        public NavigationService(IWindowManager windowManager, TVM viewModel)
        {
            _windowManager = windowManager;
            _viewModel = viewModel;
        }

        public INavigationService<TVM> WithParam<TProperty>(Expression<Func<TVM, TProperty>> property, TProperty value)
        {
            var prop = (PropertyInfo)((MemberExpression)property.Body).Member;
            prop.SetValue(_viewModel, value, null);

            return this;
        }

        public INavigationService<TVM> DoBeforeShow(Action<TVM> action)
        {
            action(_viewModel);
            return this;
        }

        public INavigationService<TVM> DoIfSuccess(System.Action action)
        {
            _action = action;
            return this;
        }

        public void ShowWindow(IDictionary<string, object> settings = null)
        {
            _windowManager.ShowWindow(_viewModel, null, settings);
        }

        public bool ShowWindowModal(IDictionary<string, object> settings = null)
        {
            bool result = _windowManager.ShowDialog(_viewModel, null, settings) ?? false;
            if (result && _action != null)
                _action();

            return result;
        }
    }
}

интерфейсы:

namespace Common
{
    public interface INavigationService<TVM>
    {
        INavigationService<TVM> WithParam<TProperty>(Expression<Func<TVM, TProperty>> property, TProperty value);

        INavigationService<TVM> DoIfSuccess(System.Action action);

        INavigationService<TVM> DoBeforeShow(Action<TVM> action);

        void ShowWindow(IDictionary<string, object> settings = null);

        bool ShowWindowModal(IDictionary<string, object> settings = null);
    }



    public interface INavigationService
    {
        INavigationService<TViewModel> GetWindow<TViewModel>();
    }
}

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

источник содержит библиотеку инфраструктуры для создания модальных диалогов, и это довольно хорошо. Поэтому я принял эту библиотеку и успешно развернул ее (я загрузил такое приложение в Codeplex).

Мне нужно было настроить код на 1 добавьте значок родителя в строку заголовка, потому что библиотека не предоставила его; и [2] Добавьте некоторый значимый текст в строку заголовка, потому что библиотека оставила его пустым и [3] Добавьте делегат для вызова при закрытии диалога. Он абстрагируется в той степени, в которой виртуальная машина может вызвать диалог, передав две строки (т. е. Unity Регистрационные имена) посреднику. Эти изменения доступны на Codeplex.

таким образом, среди всех других "стандартов" "эталонная реализация" должна минимально участвовать в качестве жизнеспособного выбора. Более косвенный ответ на ваш вопрос заключается в том, что если ваши модели представления достаточно изолированы и работают полностью через интерфейсы POCO, то теоретически это не должно иметь значения, потому что переход на другой "стандарт" должен быть тривиальным упражнением.


создание диалоговой службы хорошо сработало для меня, а также предлагается в обеих ваших ссылках.

позже я видел такое же решение в dev days в презентация MVVM от Gill Cleeren. Проверьте ссылку для рабочих образцов кода (хотя написано для Metro)

единственное, что меня немного беспокоит в диалоговой службе, - это то, что она каким-то образом зависит от технологии UI (rich client).

простое представление веб-интерфейса запроса-ответа может быть построенный поверх того же кода ViewModel и модели, к которому привязывается WPF XAML. Пока ViewModel не начнет появляться диалоговые окна через службу диалоговых окон. Я бы не знал, как реализовать диалоговую службу для веб-представления. Реализация диалогов там потребует немного больше логики для представления.


Я просто использую dialogservice, см. здесь

в вашей viewmodel вам просто нужно сделать:

var result = this.uiDialogService.ShowDialog("Dialogwindow title goes here", dialogwindowVM);

... do anything with the dialog result...

цель использования интерфейса для реализации диалогов - сделать код тестируемым. В этом случае "а" широко используется, но все равно трудно сказать "стандартный". Если у вас нет теста на ViewModel или вы можете проверить ViewModel, избегая касаться диалогов, таких как использование Extract-Override, вы можете определенно не следовать инструкции.