Форум программистов, компьютерный форум, киберфорум
C#: WPF, UWP и Silverlight
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.52/29: Рейтинг темы: голосов - 29, средняя оценка - 4.52
Модератор
8671 / 5997 / 1699
Регистрация: 21.04.2018
Сообщений: 17,848
Записей в блоге: 2
1

Использование Code Behind Окна: допустимо и, если да, то в каких случаях?

17.01.2021, 13:04. Просмотров 6030. Ответов 167
Метки нет (Все метки)

Тема создана из исходной Генерация имён при генерации элементов

Собственно вопрос данной темы это сообщение:
Цитата Сообщение от kotelok Посмотреть сообщение
Но в некоторых сценариях эта гонка за идеальной архитектурой усложняет код и/или провоцирует перенос логики из View во VM.
Предыдущие посты приведены, чтобы было понятно откуда взялся этот вопрос.

Прошу воспринимать тему не как "Священные войны", а попытку разобраться в этом вопросе, когда на практике не совсем понятна цель "запрета" на использование CB.
Особенно интересует мнение тех кто реально работает программистом в софтверной компании и знает на практики нюансы коллективной, корпоративной работы, проблемы поддержки выпущенного софта.
Возьму на себя смелость специально "пригласить": Usaga, Rius, kolorotur, Рядовой, proa33, novikov.ea, escoult.

Цитата Сообщение от Wiis Посмотреть сообщение
как для каждой пиццы и её элементов генерировать новое имя, если засунуть шаблон в цикл?
Сам шаблон:
Для начала изучить азы WPF.
В WPF есть шаблоны элементов и шаблоны данных.
А то, что вы показали - это чёрт знает, что. Но точно не шаблон.
Шаблоны задаются ИСКЛЮЧИТЕЛЬНО на XAML.
XAML - это основной язык WPF.
Code Behind в WPF не используется. Он должен оставаться пустым.
Вообще забудьте, что он существует и никогда даже не открывайте файлы "*.xaml.cs".
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
17.01.2021, 13:04
Ответы с готовыми решениями:

В каких случаях допустимо приведение указателей/ссылок на дочерний класс к базовому
В каких случаях допустимо приведение указателей/ссылок на дочерний класс к базовому?

В каких случаях оправданно использование локальных классов?
Здравствуйте. Вопрос: в каких случаях оправданно использование локальных классов? Или когда нужно...

Написание GUI руками, без привлечения специализированных фреймворков - нужно ли и если да, то в каких случаях?
Хочется узнать мнение гуру по поводу написания GUI руками.Можно ли реально от этого выиграть в...

В каких случаях использовать обращение self::, а в каких $this. В чём разница между ними?
Привет! Сейчас пишу регистрацию в стиле ооп. Пишу функцию __construct в классе Registration...

167
0 / 0 / 0
Регистрация: 29.03.2020
Сообщений: 11
17.01.2021, 13:16 2
Добавлено через 6 минут
Цитата Сообщение от Элд Хасп Посмотреть сообщение
никогда даже не открывайте файлы "*.xaml.cs".
А как тогда предлагаете писать как минимум обработчики?
0
Эксперт .NET
7494 / 4992 / 1188
Регистрация: 25.05.2015
Сообщений: 15,247
Записей в блоге: 14
17.01.2021, 13:18 3
Для этого есть команды.
0
Модератор
8671 / 5997 / 1699
Регистрация: 21.04.2018
Сообщений: 17,848
Записей в блоге: 2
17.01.2021, 13:52  [ТС] 4
Цитата Сообщение от Wiis Посмотреть сообщение
А как тогда предлагаете писать как минимум обработчики?
Для кнопок, меню и других элементов, у которых есть свойство Command, надо биндить команды.
Для остальных, в зависимости от требуемой функции, или к событиям привязываются команды, или создаются Behavior, AP свойства.

Цитата Сообщение от Wiis Посмотреть сообщение
Может вы меня не правильно поняли...
Мы вас правильно поняли, а вы нас не хотите понимать.

Это не шутка, а настоятельная рекомендация (которая для начинающих является ОБЯЗАТЕЛЬНЫМ правилом): НЕ ИСПОЛЬЗУЙТЕ Code Behind.

Все обращения (и тем более создание) к UI элементам в WPF производятся на XAML.
Это основной язык WPF.
C# вспомогательный язык и используется там где надо расширить дефолтные возможности XAML.
На нём создаются: Контекст Данных (ViewModel), конвертеры, AP и DP свойства, Behavior, триггера, различные вспомогательные типы (контейнеры, локаторы, мессенджеры, прокси и т.п.).
Но после создания эти типы используются в XAML.

Добавлено через 3 минуты
Цитата Сообщение от Wiis Посмотреть сообщение
Ок, а если убрать код который написан в xaml.cs, то получится, что программы пишутся так? Тот код я написал для динамической генерации элементов.
У Вас должен быть создан Контекст Данных.
Обычно его называют ViewModel.
В нём будет свойство-коллекция типа ObservableCollection.
В ней элементы с первичными данными.
В Окне ItemsControl (или его наследник) привязанный к этому свойству.
В шаблоне данных элемента задаётся его визуальная форма - все те элементы которые вы задавали на C#.
Всё, что касается UI элементов - делается исключительно в XAML.
0
556 / 299 / 135
Регистрация: 08.08.2014
Сообщений: 1,024
18.01.2021, 07:56 5
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Code Behind в WPF не используется. Он должен оставаться пустым
Но в некоторых сценариях эта гонка за идеальной архитектурой усложняет код и/или провоцирует перенос логики из View во VM.

Типовой пример - пользователь нажал кнопку, по которой надо:
1. Выполнить проверку состояния/настроек UI, проанализировать часть состояния VM и на основании этого принять решение перед выполнением команды запросить у пользователя подтверждение. Если пользователь отменил действие, то команду не выполнять. Это исключительно логика View. Т.е. с точки зрения VM, состояние корректно и команду можно выполнить, но с точки зрения логики View пользователь, например, установил настройку "дополнительно предупреждать меня перед выполнением этого действия".
2. Выполнить команду (собрать данные в запрос, обратиться к сервису, разобрать ответ и разложить его обратно в свойства VM) - это логикм ViewModel.
3. По результатам команды выполнить какую-то логику на стороне View как для успешного завершения, так и неудачи. Это снова логика View.

И наименее затратный (по количеству кода) и прозрачный способ сделать это - использовать CB в качестве вспомогательного инструмента (при этом с точки зрения VM команда остаётся командой и, если доп логика UI не нужна, её можно забиндить напрямую из XAML):
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
private void btnCodeBehindSample_Click(object sender, RoutedEventArgs e)
{
    //Проверка состояния и, например, какой-то мессаджбокс ok/cancel:
    //if (<user cancel>) return;
 
    //Вызов команды.
    //ViewModel.SampleCommand.ExecuteAsync();
    ViewModel.SampleCommand.ExecuteAsync().WithHandlers(
        (e) =>
        {
            //UI-специфичные действия в случае ошибки.
        }, 
        () =>
        {
            //UI-специфичные действия при успешном завершении команды.
        });
}
Да, это не использование CB, в том неуместном виде, как автор хочет, но и не полный/абсолютный отказ от него.

Можно, конечно, под каждый такой CB-обработчик свой behavior реализовывать во view-слое, но суть примерно та же получается, а сложностей в реализации больше (например, куда более заморочный DI для поведений, чем для конструктора окна/контрола).
0
Модератор
8671 / 5997 / 1699
Регистрация: 21.04.2018
Сообщений: 17,848
Записей в блоге: 2
18.01.2021, 08:02  [ТС] 6
Цитата Сообщение от kotelok Посмотреть сообщение
Типовой пример - пользователь нажал кнопку, по которой надо:
Ваш типовой пример - результат неправильной архитектуры приложения.
В приложении с правильной архитектурой никак не может возникнуть ситуация обращения в одном методе к Данным и их Представлению.
0
556 / 299 / 135
Регистрация: 08.08.2014
Сообщений: 1,024
18.01.2021, 08:18 7
Элд Хасп
Как решить данную задачу в рамках правильной архитектуры?

В слое View есть UI-специфичный сервис настроек пользователя, который ни к ViewModel, ни к Модели отношения не имеет. Это чисто View-логика.

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

И проверка подвтерждения завязана на текущее состояние VM, т.е. она выполняется, например, только если пользователь внёс изменения в конкретное поле. При этом с точки зрения VM и Модели данные корректны и могут быть сохранены, но на уровне UI требуется доп-уведомление.
0
Модератор
8671 / 5997 / 1699
Регистрация: 21.04.2018
Сообщений: 17,848
Записей в блоге: 2
18.01.2021, 08:23  [ТС] 8
Цитата Сообщение от kotelok Посмотреть сообщение
Можно, конечно, под каждый такой CB-обработчик свой behavior реализовывать во view-слое....
Дело не в этом.

Во первых, описанный вами функционал метода очень обширен. Это просто какой-то "метод Бога".
В ООП, в принципе, не желательно делать такие методы.

Кроме Behavior можно можно сделать реализацию обработчика в XAML или в отдельном статическом классе.
Оба варианты тоже лучше чем CB.
Но то что вы описали по функциям для метода - не подойдёт для этих обоих вариантов.
Функционал перегружен и надо его разбивать на отдельные методы - то есть упирается, как я уже написал, в неправильную архитектуру приложения.

Ну и напоследок, "никогда не использовать Code Behind" - это требование к начинающим. Тем кто только учится и в будущем намерен заниматься профессиональным программированием.
К сожалению, в настоявшее время современное программирование преподают отвратительно.
Преподаватели, похоже, об ООП знают только расшифровку аббревиатуры.
О том, что XAML - это самостоятельный язык, такой же как C# и его так же надо изучать, они и не знают.
Поэтому, чтобы научиться WPF и изучить все "его прелести" надо в первую очередь изучать XAML и Привязки.
Если начинающий начнёт вместо этого клепать процедурные костыли в CB - он никогда не изучит XAML.

Добавлено через 2 минуты
Цитата Сообщение от kotelok Посмотреть сообщение
Как решить данную задачу в рамках правильной архитектуры?
Вы дали слишком общее, без деталей описание.
Я не смогу дать ответы по такой формулировке.
0
Модератор
8671 / 5997 / 1699
Регистрация: 21.04.2018
Сообщений: 17,848
Записей в блоге: 2
18.01.2021, 08:31  [ТС] 9
Цитата Сообщение от kotelok Посмотреть сообщение
В слое View есть UI-специфичный сервис настроек пользователя, который ни к ViewModel, ни к Модели отношения не имеет. Это чисто View-логика.
Откуда берутся эти настройки и как они сохраняются?
Если это какой-то несохраняемый CheckBox - это одна задача.
Если это сохраняемые настройки, то это совсем другая задача решаемая отдельной VM.
Она может быть как вложенной в основную (через интерфейс или дочерняя), так и быть независимой, получаемой через локатор или Ресурсы.
0
управление сложностью
1572 / 1218 / 235
Регистрация: 22.03.2015
Сообщений: 7,072
Записей в блоге: 4
18.01.2021, 08:37 10
Цитата Сообщение от kotelok Посмотреть сообщение
В слое View есть UI-специфичный сервис настроек пользователя, который ни к ViewModel, ни к Модели отношения не имеет. Это чисто View-логика.
Позвольте не согласиться. Настройки пользователя - это состояние модели в определенный момент времени, т.к. модель может находиться в разных состояниях при запуске, при работе, при завершении работы, так что считаю настройки - это часть модели.

Добавлено через 1 минуту
Цитата Сообщение от kotelok Посмотреть сообщение
И там конкретный пользователь установил себе настройку "запрашивать дополнительное подтверждение при выполнении определённого действия".
Про что я и говорил - модель должна знать, что юзверю требуется дополнительно подтверждать действия.

Добавлено через 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
управление сложностью
1572 / 1218 / 235
Регистрация: 22.03.2015
Сообщений: 7,072
Записей в блоге: 4
18.01.2021, 08:48 12
Цитата Сообщение от kotelok Посмотреть сообщение
Но с точки зрения логики конкретного окна на конкретной платформе и окружении, т.е. с точки зрения именно View-логики, в каком-то случае нужно показать пользователю дополнительное подтверждение действия, которое ни на какие данные не влияет, а просто немного дополнияет UI-логику и, в случае отказа пользователя, вовсе отменяет запрос выполнения команды у VM.
Это имеет смысл для подтверждения действия, типа - "вы действительно хотите эту операцию ?". И не более. Что делать, если потребуется логировать действия пользователя, в т.ч. и отказы ? Расширить логику всегда проще, когда работа логики сосредоточена в одном месте, чем размазана по всем слоям.

Добавлено через 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
управление сложностью
1572 / 1218 / 235
Регистрация: 22.03.2015
Сообщений: 7,072
Записей в блоге: 4
18.01.2021, 09:36 14
Цитата Сообщение от kotelok Посмотреть сообщение
необходимо вывести пользователю уведомление и, если пользователь нажал 'yes', отобразить ещё какую-то форму. И вот эту логику предлагается опускать куда-то ниже View?
Да, т.к. х.з. что еще в будущем пригодится, в том плане, что в дополнительной форме еще могут быть какие-то данные и работа с ними, в т.ч. и работа с логикой. Отображением вьюх должен же заниматься "отдельный сервис" ?
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
управление сложностью
1572 / 1218 / 235
Регистрация: 22.03.2015
Сообщений: 7,072
Записей в блоге: 4
18.01.2021, 12:41 16
kotelok, все-равно, я не могу принять вашу точку зрения именно в этом вопросе - подверждение действия. Если это требование - то оно должно быть частью домена, если свистоперделка - то можно и на уровне вьюхи оставить.
0
Модератор
8671 / 5997 / 1699
Регистрация: 21.04.2018
Сообщений: 17,848
Записей в блоге: 2
18.01.2021, 16:46  [ТС] 17
Цитата Сообщение от kotelok Посмотреть сообщение
Простой пример:
Моё видение правильной архитектуры (один из вариантов).
У вас есть две View. Одна основная - с данными которые надо сохранить, вторая - диалог подтверждения.
Диалог должен возвращать результат выбора пользователя, но сам по себе он ничего не делает.
В команде VM первым делом запрашивается Диалог (по делегату полученному при создании VM).
По результату Диалога - дальнейшие ветвление действий.

Добавлено через 7 минут
Другой вариант, когда VM "не знает" ничего о Диалоге.
Создаёте прокси-команду в ресурсах - не забываем, что команда может быть и View компонентой.
В прокси задаются необходимые действия по вызову и анализу Диалога.
Там же, если нужно, вызывается метод VM.
Этот же вариант можно осуществить и обработкой Click в статическом классе - где в разделе есть мой пример с таки кодом.
1
556 / 299 / 135
Регистрация: 08.08.2014
Сообщений: 1,024
18.01.2021, 16:53 18
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Моё видение правильной архитектуры (один из вариантов).
У вас есть две View. Одна основная - с данными которые надо сохранить, вторая - диалог подтверждения.
Диалог должен возвращать результат выбора пользователя, но сам по себе он ничего не делает.
В команде VM первым делом запрашивается Диалог (по делегату полученному при создании VM).
По результату Диалога - дальнейшие ветвление действий.
Т.е. получается, что часть логики View всё-таки уходит во ViewModel? Т.е. VM начинает, пусть и через абстракцию, запрашивать взаимодействие с пользователем?

А если это не просто диалог подтверждения, а ещё один типовой сценарий - в гриде произошёл даблклик в айтем, нужно показать модальный диалог редактирования записи, то это тоже через VM будет реализовываться, т.е.:
1. Событие даблклика из View через EventToCommand биндится на команду VM.
2. VM запрашивает через фабрику VM для окна редактирования записи, выдаёт ей ID записи и далее, через какой-нибудь сервис, запрашивает поиск и отображение окна для данной VM? Т.е. 'viewService.ShowDialog(itemEditViewModel);'.

Я этот вариант пробовал - в итоге внутри VM скапливается много логики, которая нужна исключительно для UI, которая с моделью не взаимодействует, и которая намного более логично смотрится в CB-окна.
0
Модератор
8671 / 5997 / 1699
Регистрация: 21.04.2018
Сообщений: 17,848
Записей в блоге: 2
18.01.2021, 16:57  [ТС] 19
В любом случае, вы может этого не видите, но ваши задачи в сообщениях 18 и 30, на мой взгляд, принципиально разные.
В первом случае речь шла об обработке UI элементов и Данных (вызов метода VM) в одном методе.
Во втором, создание Диалога и, по его результату, вызов метода VM.

Диалог - это "вещь в себе".
Его можно создавать независимо от основной View. В том числе вы можете использовать статический обработчик.
А если вам нужны UI элементы из основной View, то создать статический обработчик не получится.
А это признак нарушения архитектуры.

Добавлено через 3 минуты
Цитата Сообщение от kotelok Посмотреть сообщение
Т.е. получается, что часть логики View всё-таки уходит во ViewModel? Т.е. VM начинает, пусть и через абстракцию, запрашивать взаимодействие с пользователем?
Распределение функционала между View и VM не всегда однозначно.
Это задаётся при проектировании архитектуры приложения.
Вы вполне можете на практике сделать библиотечный тип для Диалога вызываемый из VM.
Так же можно это реализовать и в App - ведь Диалог это отдельная независимая View.
И основная View необязательно должна о нём знать.
1
556 / 299 / 135
Регистрация: 08.08.2014
Сообщений: 1,024
18.01.2021, 16:57 20
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Создаёте прокси-команду в ресурсах - не забываем, что команда может быть и View компонентой.
В прокси задаются необходимые действия по вызову и анализу Диалога.
Там же, если нужно, вызывается метод VM.
Этот же вариант можно осуществить и обработкой Click в статическом классе - где в разделе есть мой пример с таки кодом.
Но ведь это всё полностью изолировано внутри View-сборки? Т.е. все эти прокси-команды или обработка клика через статический класс, поведения - это просто блоки C#-кода, закрытые в ту же сборку, что и XAML. Ну или, если это что-то переиспользуемое, то вынесенное в отдельную библиотеку, на которую ссылается View-сборка.

Чем тогда хуже CB, который точно так же не выходит за рамки View-логики, точно так же закрыт внутри сборки View и реализует ровно ту же логику?
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
18.01.2021, 16:57

Заказываю контрольные, курсовые, дипломные и любые другие студенческие работы здесь.

В каких случаях уместно применять F-критерий, а в каких - эмпирическое корреляционное отношение?
Дисперсионный анализ Доброго времени суток! Подскажите, пожалуйста, в каких случаях уместно...

В каких случаях нужно создавать динамические переменные, а в каких статические?
такой же вопрос и по массивам ! Объясните пожалуйста !

В каких случаях нужно использовать подключаемый уровень, а в каких автономный
Добрый день. Изучаю материал по работе с ADO.NET и у меня возник такой вопрос: 1.- В каких случаях...

В каких случаях надо создавать индексы к полям, а в каких - нет?
Не могу понять, в каком случае надо создовать индексы к полям а вкаких нет. если надо, то в каком...

В каких случаях создаётся имя в кодировке utf-16 файла или папки, а в каких нет?
Друзья! Вынужден ковыряться со сторонними файлами, где без кодировки utf-16 не обойтись, век бы её...

В каких случаях надо ставить datatype, а в каких type? (ML)
Не могу понять, в каких случаях надо ставить datatype , а в каких type ? например datatype bool...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.