Страницы

Поиск по вопросам

четверг, 8 ноября 2018 г.

OpenFileDialog и MVVM

Подскажите, каким правильно пойти путем.
На форме WPF есть кнопка "Обзор", которая должна вызвать OpenFileDialog и после выбора файла передать его имя в textbox
Используя паттерн MVVM, я должен не менять значение textbox, а изменить соответствующие значение в VM. И вот мой вопрос. Вызов OpenFileDialog я должен сделать в VM как ICommand, или из своей формы на которой кнопка?


Ответ

Диалоги-краеугольный камень MVVM ибо предполагается, что VM о View ничего не знает, но должен получать от неё данные. Получаем, что с одной стороны View должна вызывать команды VM с параметрами и VM ну никак не должна работать с отображением. Т.е. диалоги относятся к View. А с другой: View не должна содержать логики/кода, а вызов диалогового окна и получение результата это какая никакая а логика/код.
Самый простой вариант: в коде View повесьте обработчик события на то событие по которому у вас должен отображаться диалог выбора файла в котором создаёте и отображаете диалог пользователю, а по факту успешного закрытия события вызываете команду VM из кода (в этом случае можно обойтись и интерфейсным методом, без объявления команды).
В код на стороне VM Должна приходить строка пути к открываемому файлу(лам) и, возможно, тип доступа (чтение/чтение-запись и тп.)
PS: Если вы придерживаетесь MVVM при разработке, имхо, главное, что следует всегда помнить: вы должны сохранять тестируемость Unit-тестами вашей VM. (т.е. если вместо M подсунуть тестовые данные, а вместо View напрямую вызвать команды у вас все публичные методы и команды должны тестироваться без танцев с бубном) Создание в VM диалогов ломает эту схему.
Вариант посложнее: Иногда случается так, что диалог нужен кастомный. С кучей параметров которые должны задаваться на уровне VM. И вообще возможно так, что въюха должна контролировать диалог (т.е. например сначала отобразить его, а потом начать перемещать его по экрану, а потом ещё что-то эдакое) В этом случае возможно воспользоваться делегатами которые вы определяете на уровне VM. Входные и выходные параметры вы определяете так же в VM. Присвоение метода делегату осуществляется в коде который относится ко View. В нем реализуется отображение диалога (или чего бы то ни было ещё) и логика поведения/управления отображением. На выход вы, в принципе, можете передавать всё что угодно, начиная от результата диалога и заканчивая объектом реализующим объявленный вами интерфейс через который вы контролируете окно. Этот вариант по коду выходит чуть компактнее варианта с интерфейсами. Тестируемость не страдает.
PSS: Имхо, "правильного" варианта вне глобального контекста задачи не существует. Помните, что "Hello World" написанный по всем канонам и стандартам это овер 100 строк кода. Варианты с интерфейсами/делегатами и пр. танцами с бубном и десятком сопутствующих классов специфичны, сложны в понимании, сопровождении и отладке (!) и нужны только в случае если у вас этих диалогов (разных видов) больше 3 и ожидаются ещё в будущем к тому же они все нестандартные и со сложным поведением. В общем "Не усложняйте" (с)

Комментариев нет:

Отправить комментарий