Модератор
|
|
1 | |
Использование Code Behind Окна: допустимо и, если да, то в каких случаях?17.01.2021, 13:04. Просмотров 6030. Ответов 167
Метки нет Все метки)
(
Тема создана из исходной Генерация имён при генерации элементов
Собственно вопрос данной темы это сообщение: Предыдущие посты приведены, чтобы было понятно откуда взялся этот вопрос. Прошу воспринимать тему не как "Священные войны", а попытку разобраться в этом вопросе, когда на практике не совсем понятна цель "запрета" на использование CB. Особенно интересует мнение тех кто реально работает программистом в софтверной компании и знает на практики нюансы коллективной, корпоративной работы, проблемы поддержки выпущенного софта. Возьму на себя смелость специально "пригласить": Usaga, Rius, kolorotur, Рядовой, proa33, novikov.ea, escoult. Для начала изучить азы WPF. В WPF есть шаблоны элементов и шаблоны данных. А то, что вы показали - это чёрт знает, что. Но точно не шаблон. Шаблоны задаются ИСКЛЮЧИТЕЛЬНО на XAML. XAML - это основной язык WPF. Code Behind в WPF не используется. Он должен оставаться пустым. Вообще забудьте, что он существует и никогда даже не открывайте файлы "*.xaml.cs".
0
|
|
17.01.2021, 13:04 | |
Написание GUI руками, без привлечения специализированных фреймворков - нужно ли и если да, то в каких случаях? В каких случаях использовать обращение self::, а в каких $this. В чём разница между ними? |
|
0 / 0 / 0
Регистрация: 29.03.2020
Сообщений: 11
|
|
17.01.2021, 13:16 | 2 |
Добавлено через 6 минут
А как тогда предлагаете писать как минимум обработчики?
0
|
Модератор
|
|
17.01.2021, 13:52 [ТС] | 4 |
Для кнопок, меню и других элементов, у которых есть свойство Command, надо биндить команды.
Для остальных, в зависимости от требуемой функции, или к событиям привязываются команды, или создаются Behavior, AP свойства. Мы вас правильно поняли, а вы нас не хотите понимать. Это не шутка, а настоятельная рекомендация (которая для начинающих является ОБЯЗАТЕЛЬНЫМ правилом): НЕ ИСПОЛЬЗУЙТЕ Code Behind. Все обращения (и тем более создание) к UI элементам в WPF производятся на XAML. Это основной язык WPF. C# вспомогательный язык и используется там где надо расширить дефолтные возможности XAML. На нём создаются: Контекст Данных (ViewModel), конвертеры, AP и DP свойства, Behavior, триггера, различные вспомогательные типы (контейнеры, локаторы, мессенджеры, прокси и т.п.). Но после создания эти типы используются в XAML. Добавлено через 3 минуты У Вас должен быть создан Контекст Данных. Обычно его называют ViewModel. В нём будет свойство-коллекция типа ObservableCollection. В ней элементы с первичными данными. В Окне ItemsControl (или его наследник) привязанный к этому свойству. В шаблоне данных элемента задаётся его визуальная форма - все те элементы которые вы задавали на C#. Всё, что касается UI элементов - делается исключительно в XAML.
0
|
556 / 299 / 135
Регистрация: 08.08.2014
Сообщений: 1,024
|
||||||
18.01.2021, 07:56 | 5 | |||||
Но в некоторых сценариях эта гонка за идеальной архитектурой усложняет код и/или провоцирует перенос логики из View во VM.
Типовой пример - пользователь нажал кнопку, по которой надо: 1. Выполнить проверку состояния/настроек UI, проанализировать часть состояния VM и на основании этого принять решение перед выполнением команды запросить у пользователя подтверждение. Если пользователь отменил действие, то команду не выполнять. Это исключительно логика View. Т.е. с точки зрения VM, состояние корректно и команду можно выполнить, но с точки зрения логики View пользователь, например, установил настройку "дополнительно предупреждать меня перед выполнением этого действия". 2. Выполнить команду (собрать данные в запрос, обратиться к сервису, разобрать ответ и разложить его обратно в свойства VM) - это логикм ViewModel. 3. По результатам команды выполнить какую-то логику на стороне View как для успешного завершения, так и неудачи. Это снова логика View. И наименее затратный (по количеству кода) и прозрачный способ сделать это - использовать CB в качестве вспомогательного инструмента (при этом с точки зрения VM команда остаётся командой и, если доп логика UI не нужна, её можно забиндить напрямую из XAML):
Можно, конечно, под каждый такой CB-обработчик свой behavior реализовывать во view-слое, но суть примерно та же получается, а сложностей в реализации больше (например, куда более заморочный DI для поведений, чем для конструктора окна/контрола).
0
|
Модератор
|
|
18.01.2021, 08:02 [ТС] | 6 |
Ваш типовой пример - результат неправильной архитектуры приложения.
В приложении с правильной архитектурой никак не может возникнуть ситуация обращения в одном методе к Данным и их Представлению.
0
|
556 / 299 / 135
Регистрация: 08.08.2014
Сообщений: 1,024
|
|
18.01.2021, 08:18 | 7 |
Элд Хасп
Как решить данную задачу в рамках правильной архитектуры? В слое View есть UI-специфичный сервис настроек пользователя, который ни к ViewModel, ни к Модели отношения не имеет. Это чисто View-логика. И там конкретный пользователь установил себе настройку "запрашивать дополнительное подтверждение при выполнении определённого действия". И проверка подвтерждения завязана на текущее состояние VM, т.е. она выполняется, например, только если пользователь внёс изменения в конкретное поле. При этом с точки зрения VM и Модели данные корректны и могут быть сохранены, но на уровне UI требуется доп-уведомление.
0
|
Модератор
|
|
18.01.2021, 08:23 [ТС] | 8 |
Дело не в этом.
Во первых, описанный вами функционал метода очень обширен. Это просто какой-то "метод Бога". В ООП, в принципе, не желательно делать такие методы. Кроме Behavior можно можно сделать реализацию обработчика в XAML или в отдельном статическом классе. Оба варианты тоже лучше чем CB. Но то что вы описали по функциям для метода - не подойдёт для этих обоих вариантов. Функционал перегружен и надо его разбивать на отдельные методы - то есть упирается, как я уже написал, в неправильную архитектуру приложения. Ну и напоследок, "никогда не использовать Code Behind" - это требование к начинающим. Тем кто только учится и в будущем намерен заниматься профессиональным программированием. К сожалению, в настоявшее время современное программирование преподают отвратительно. Преподаватели, похоже, об ООП знают только расшифровку аббревиатуры. О том, что XAML - это самостоятельный язык, такой же как C# и его так же надо изучать, они и не знают. Поэтому, чтобы научиться WPF и изучить все "его прелести" надо в первую очередь изучать XAML и Привязки. Если начинающий начнёт вместо этого клепать процедурные костыли в CB - он никогда не изучит XAML. Добавлено через 2 минуты Вы дали слишком общее, без деталей описание. Я не смогу дать ответы по такой формулировке.
0
|
Модератор
|
|
18.01.2021, 08:31 [ТС] | 9 |
Откуда берутся эти настройки и как они сохраняются?
Если это какой-то несохраняемый CheckBox - это одна задача. Если это сохраняемые настройки, то это совсем другая задача решаемая отдельной VM. Она может быть как вложенной в основную (через интерфейс или дочерняя), так и быть независимой, получаемой через локатор или Ресурсы.
0
|
управление сложностью
|
|
18.01.2021, 08:37 | 10 |
Позвольте не согласиться. Настройки пользователя - это состояние модели в определенный момент времени, т.к. модель может находиться в разных состояниях при запуске, при работе, при завершении работы, так что считаю настройки - это часть модели.
Добавлено через 1 минуту Про что я и говорил - модель должна знать, что юзверю требуется дополнительно подтверждать действия. Добавлено через 2 минуты P.S. WPF - это как с ASP, мало знать язык, нужно еще знать как работает механизм ASP
0
|
556 / 299 / 135
Регистрация: 08.08.2014
Сообщений: 1,024
|
|
18.01.2021, 08:42 | 11 |
Нет, не должна. Это исключительно часть UI-логики конкретного окна. С точки зрения VM - данные корректны, с точки зрения модели (конкретного API-метода на сервере) тоже всё в порядке и данные могут быть сохрнены без ошибок. Но с точки зрения логики конкретного окна на конкретной платформе и окружении, т.е. с точки зрения именно View-логики, в каком-то случае нужно показать пользователю дополнительное подтверждение действия, которое ни на какие данные не влияет, а просто немного дополнияет UI-логику и, в случае отказа пользователя, вовсе отменяет запрос выполнения команды у VM.
Зачем вообще может понадобиться опускать эту логику ниже View-слоя?
0
|
управление сложностью
|
|
18.01.2021, 08:48 | 12 |
Это имеет смысл для подтверждения действия, типа - "вы действительно хотите эту операцию ?". И не более. Что делать, если потребуется логировать действия пользователя, в т.ч. и отказы ? Расширить логику всегда проще, когда работа логики сосредоточена в одном месте, чем размазана по всем слоям.
Добавлено через 1 минуту И настройки юзверя - это скорее больше сервисный слой, чем представления.
1
|
556 / 299 / 135
Регистрация: 08.08.2014
Сообщений: 1,024
|
|
18.01.2021, 09:23 | 13 |
У каждого слоя своя логика, которая не должна влиять и просачиваться в слои уровнем ниже.
Есть модель, представленная каким-то внешним сервисом, который реализует стандартный набор CRUD-операций над некой сущностью (/api/some). К этому слою вообще может не быть доступа на доработку, это просто внешний API. Есть VM, которая обращается к этой модели, получает оттуда данные и выставляеет их в виде INPC-свойств. Так же предоставляет команду для обновления данных, которую транслирует в вызов API-метода. И есть View под конкретную платформу, поверх обозначнной выше VM. И вот именно в десктопной версии View нужна доп-логика, когда после успешного выполнения команды на сохранение, необходимо вывести пользователю уведомление и, если пользователь нажал 'yes', отобразить ещё какую-то форму. И вот эту логику предлагается опускать куда-то ниже View? Т.е. всю эта навигацию и прочие view-специфичные вещи, которые ни к VM, ни к модели никакого отношения не имеют.
0
|
управление сложностью
|
|
18.01.2021, 09:36 | 14 |
Да, т.к. х.з. что еще в будущем пригодится, в том плане, что в дополнительной форме еще могут быть какие-то данные и работа с ними, в т.ч. и работа с логикой. Отображением вьюх должен же заниматься "отдельный сервис" ?
0
|
556 / 299 / 135
Регистрация: 08.08.2014
Сообщений: 1,024
|
|
18.01.2021, 12:32 | 15 |
Это уже детали реализации. Но этот сервис (который отвечает за навигацию между окнами) всё равно относится к view-слою, а не к VM, и уж точно не внешнему API-сервису, который про логику конкретного UI ничего не знает.
Добавлено через 2 часа 51 минуту Как в этом случае принять решение в рамках UI-логики? Если к данным доступа нет? Простой пример: 1. Пользователь нажал кнопку "сохранить". 2. С точки зрения VM (и модели) данные корректны и могут быть сохранены. Там нет и не требуется никакой дополнительной логики. 3. Но с точки зрения реализации конкретной части UI - есть требование "показать подтверждение действия, если в каком-то поле выбрано определённое значение". Это требование конкретного View, но не VM (поверх которой может быть ещё и другой View, которому эта логика подтверждения не нужна). Очевидно, что в данном случае код, который принимает решение о выводе подтверждения и отмене выполнения команды (если пользователь нажал 'no'): 1. Работает именно на уровне View. 2. Должен иметь доступ к данным VM, дабы принять решение в рамках своей логики. Т.е. он имеет доступ и к представлению, и к данным (VM).
0
|
управление сложностью
|
|
18.01.2021, 12:41 | 16 |
kotelok, все-равно, я не могу принять вашу точку зрения именно в этом вопросе - подверждение действия. Если это требование - то оно должно быть частью домена, если свистоперделка - то можно и на уровне вьюхи оставить.
0
|
Модератор
|
|
18.01.2021, 16:46 [ТС] | 17 |
Моё видение правильной архитектуры (один из вариантов).
У вас есть две View. Одна основная - с данными которые надо сохранить, вторая - диалог подтверждения. Диалог должен возвращать результат выбора пользователя, но сам по себе он ничего не делает. В команде VM первым делом запрашивается Диалог (по делегату полученному при создании VM). По результату Диалога - дальнейшие ветвление действий. Добавлено через 7 минут Другой вариант, когда VM "не знает" ничего о Диалоге. Создаёте прокси-команду в ресурсах - не забываем, что команда может быть и View компонентой. В прокси задаются необходимые действия по вызову и анализу Диалога. Там же, если нужно, вызывается метод VM. Этот же вариант можно осуществить и обработкой Click в статическом классе - где в разделе есть мой пример с таки кодом.
1
|
556 / 299 / 135
Регистрация: 08.08.2014
Сообщений: 1,024
|
|
18.01.2021, 16:53 | 18 |
Т.е. получается, что часть логики View всё-таки уходит во ViewModel? Т.е. VM начинает, пусть и через абстракцию, запрашивать взаимодействие с пользователем?
А если это не просто диалог подтверждения, а ещё один типовой сценарий - в гриде произошёл даблклик в айтем, нужно показать модальный диалог редактирования записи, то это тоже через VM будет реализовываться, т.е.: 1. Событие даблклика из View через EventToCommand биндится на команду VM. 2. VM запрашивает через фабрику VM для окна редактирования записи, выдаёт ей ID записи и далее, через какой-нибудь сервис, запрашивает поиск и отображение окна для данной VM? Т.е. 'viewService.ShowDialog(itemEditViewModel);'. Я этот вариант пробовал - в итоге внутри VM скапливается много логики, которая нужна исключительно для UI, которая с моделью не взаимодействует, и которая намного более логично смотрится в CB-окна.
0
|
Модератор
|
|
18.01.2021, 16:57 [ТС] | 19 |
В любом случае, вы может этого не видите, но ваши задачи в сообщениях 18 и 30, на мой взгляд, принципиально разные.
В первом случае речь шла об обработке UI элементов и Данных (вызов метода VM) в одном методе. Во втором, создание Диалога и, по его результату, вызов метода VM. Диалог - это "вещь в себе". Его можно создавать независимо от основной View. В том числе вы можете использовать статический обработчик. А если вам нужны UI элементы из основной View, то создать статический обработчик не получится. А это признак нарушения архитектуры. Добавлено через 3 минуты Распределение функционала между View и VM не всегда однозначно. Это задаётся при проектировании архитектуры приложения. Вы вполне можете на практике сделать библиотечный тип для Диалога вызываемый из VM. Так же можно это реализовать и в App - ведь Диалог это отдельная независимая View. И основная View необязательно должна о нём знать.
1
|
556 / 299 / 135
Регистрация: 08.08.2014
Сообщений: 1,024
|
|
18.01.2021, 16:57 | 20 |
Но ведь это всё полностью изолировано внутри View-сборки? Т.е. все эти прокси-команды или обработка клика через статический класс, поведения - это просто блоки C#-кода, закрытые в ту же сборку, что и XAML. Ну или, если это что-то переиспользуемое, то вынесенное в отдельную библиотеку, на которую ссылается View-сборка.
Чем тогда хуже CB, который точно так же не выходит за рамки View-логики, точно так же закрыт внутри сборки View и реализует ровно ту же логику?
0
|
18.01.2021, 16:57 | |
Заказываю контрольные, курсовые, дипломные и любые другие студенческие работы здесь. В каких случаях уместно применять F-критерий, а в каких - эмпирическое корреляционное отношение?
В каких случаях нужно использовать подключаемый уровень, а в каких автономный В каких случаях надо создавать индексы к полям, а в каких - нет? В каких случаях создаётся имя в кодировке utf-16 файла или папки, а в каких нет? В каких случаях надо ставить datatype, а в каких type? (ML) Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |