Форум программистов, компьютерный форум, киберфорум
C#: WPF, UWP и Silverlight
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
2298 / 1614 / 400
Регистрация: 26.06.2017
Сообщений: 4,780
Записей в блоге: 1

MVVM блокировка кнопки до валидации

10.04.2025, 10:56. Показов 6476. Ответов 71
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый день.

Исходные данные: разработка в шаблоне MVVM, у некоего окна есть кнопка "ОК", к которой в xaml привязана команда из VM. Также на уровне VM делается валидация данных при помощи INotifyDataErrorInfo. При открытии окна кнопка "ОК" доступна для нажатия хотя дефолтные данные в окне не валидны. Кнопка блокируется если начать вводить не правильные данные, то есть кнопка реагирует только тогда, когда начинает работать механизм валидации.

Вопрос в следующем: как при открытии окна сделать кнопку "ОК" недоступной для нажатия с сохранение её зависимости от CanExecute изменяемой при валидации?

Добавлено через 5 минут
Дополнительное пояснение. Допустим есть одно текстовое поле, которое не может быть пустым и эта проверка делается в VM, после чего устанавливается HasErrors, на который и реагирует кнопка. Но сразу после открытия окна поле пустое и если его не трогать оно также остаётся пустым (не валидным), но в этом случае HasErrors не устанавливается.
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
10.04.2025, 10:56
Ответы с готовыми решениями:

Обработка валидации данных в слое VM (MVVM)
Доброго дня всем. Понимаю, что тема избита, но так как я только изучаю WPF и его применение в...

Рисую линию без MVVM все ОК. C MVVM произвольный старт
Добрый день всем. Рисую линию при помощи анимации. Все получилось -рисуется, стирается. Но у...

Приложение MVVM. Быстрая "Нестрогая MVVM" реализация
В этой теме будет размещена простая и быстрая реализация. Основная тема:...

71
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,176
Записей в блоге: 2
13.04.2025, 22:13
Студворк — интернет-сервис помощи студентам
C#
90
    private bool IsValid(PersonDTO validatingPerson)
Чем этот метод отличается от значения HasErrors ?
0
2298 / 1614 / 400
Регистрация: 26.06.2017
Сообщений: 4,780
Записей в блоге: 1
13.04.2025, 22:14  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Не пойму зачем это свойство-делегат нужно.
Через этот делегат сохраняется PersonDTO в MainWindowViewModel. Это сделано так потому, что PersonViewModel понятия не имеет, что делать с PersonDTO после того как пользователь закончил ввод данных.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,176
Записей в блоге: 2
13.04.2025, 22:14
HasErrors - не взводится при старте PersonViewModel. Верно?
0
2298 / 1614 / 400
Регистрация: 26.06.2017
Сообщений: 4,780
Записей в блоге: 1
13.04.2025, 22:16  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Чем этот метод отличается от значения HasErrors ?
Особо ничем кроме того, что в нём показан второй способ вызова Validate. Я об этом в описании написал.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,176
Записей в блоге: 2
13.04.2025, 22:16
Цитата Сообщение от Uswer Посмотреть сообщение
Это сделано так потому, что PersonViewModel понятия не имеет, что делать с PersonDTO после того как пользователь закончил ввод данных.
А...
То есть вы хотите сделать PersonViewModel просто оболочкой, прокси объектом. Без прямой связи с Моделью. Верно?
0
2298 / 1614 / 400
Регистрация: 26.06.2017
Сообщений: 4,780
Записей в блоге: 1
13.04.2025, 22:17  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
HasErrors - не взводится при старте PersonViewModel. Верно?
Верно. И кнопка Save не привязана к HasErrors.

Добавлено через 39 секунд
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Без прямой связи с Моделью. Верно?
Абсолютно верно. С моделью связана MainWindowViewModel.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,176
Записей в блоге: 2
13.04.2025, 22:23
Тогда нет, вообще, смысла в команде SaveCommand. Её нужно перекинуть в MainVM.

Цитата Сообщение от Uswer Посмотреть сообщение
Я об этом в описании написал.
ReadMe к репозиторию. Не заметил его. Прочитал сейчас.

Добавлено через 1 минуту
Зачем, вообще, нужен PersonDTO в PersonViewModel?
Только лишняя морока с ним.

Добавлено через 2 минуты
C#
90
private bool IsValid(PersonDTO validatingPerson)
Чё-то перемудрили с проверками.
C#
90
91
        private bool IsValid(PersonDTO validatingPerson)
            => Validate(validatingPerson.Name, "Name") & Validate(validatingPerson.Birthday, "DateOfBirth");
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,176
Записей в блоге: 2
13.04.2025, 22:31
Переходим к MainWindowViewModel.

Добавлено через 1 минуту
C#
9
public ObservableCollection<Model.PersonDTO> People { get; }
Мутабельная коллекция с мутабельными элементами.
Её вполне можно редактировать напрямую в DataGrid. В такой реализации теряет смысл отдельное окно добавления.

Добавлено через 1 минуту
C#
20
21
22
23
24
25
26
27
28
29
30
    private void OnAddPersonCommandExecute(object obj)
    {
      var vm = new PersonViewModel();
 
      var _personWindow = new AddPersonWindow()
      {
        DataContext = vm
      };
      vm.SaveChanges = new Action<Model.PersonDTO>(SetPersonChanges);
      _personWindow.Show();
    }
Это вообще треш.
VM напрямую управляет окном.
Это грубейшее нарушение MVVM.

Добавлено через 2 минуты
В таком как у вас функционале, я бы в слое VM оставил только MainWindowViewModel.

Команда AddPersonCommand должна быть перенесена в View.
PersonViewModel - тоже особого смыла находится в слое в VM нет.
Надо команду SaveCommand перенести в MainWindowViewModel, а сам PersonViewModel в слой View.
0
2298 / 1614 / 400
Регистрация: 26.06.2017
Сообщений: 4,780
Записей в блоге: 1
13.04.2025, 22:44  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Зачем, вообще, нужен PersonDTO в PersonViewModel?
Да да, я увидел в вашел пулл реквесте, что можно вообще без этого PersonDTO обойтись.

Добавлено через 8 минут
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Надо команду SaveCommand перенести в MainWindowViewModel, а сам PersonViewModel в слой View.
Вот тут я окончательно потерялся в MVVM. По какому принципу тот или иной код распределяется по слоям?
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,176
Записей в блоге: 2
14.04.2025, 07:49
Цитата Сообщение от Uswer Посмотреть сообщение
По какому принципу тот или иной код распределяется по слоям?
У вас не выделена бизнес-логика в отдельный слой.
Поэтому вам трудно понять границы функционала.

В моём примере (pull request) бизнес логика - это создание Person, поддержание локального кеша people. функции по его изменению (пока реализовано только добавление Person).

Следовательно функция ViewModel - это отражение этой Бизнес-Логики в eдобном для View виде.

Теперь подумаем.
Открытие Окна AddPerson как-то меняет на модель, задействует бизнес-логику (описанную выше)?
Нет. Бизнес логика здесь не причём.
Следовательно, раз состояние Модели не меняется, то и её отражение в VM не должно меняться.
Отсюда очевидный вывод.
Если из PersonViewModel убрать команду SaveCommand, то там вовсе не остаётся никакой связи с моделью, с бизнес логикой.
А команда SaveCommand даже в нынешнем функционале, по сути это просто прокидывание логики MainVM и нет никакой необходимости в такой прокси команде. В View можно сразу использовать команду из MainVM.

Вот и получается, что PersonViewModel никак не относится к слою VM.

Возможно вас немного путает задание Контекста Данных.
Многие воспринимают Контекст Данных = ViewModel.
Но это не так.
Контекст Данных - это просто способ задания источника по умолчанию для привязок.
Чаще всего в нём бывает VM, но это просто вопрос удобства работы и упрощения реализации.
Это не обязательное условие.
У вас может VM состоять из множества отдельных источников. И ни один из них может не быть в Контексте Данных конкретного окна.

Например в вашей задаче напрашивается, создание экземпляра MainVM в ресурсах App (можно непосредственно или в свойстве локатора). Основное Окно получает его из ресурсов App, а не создаёт самостоятельно.
А Окно AddPerson в свой контекст получает прокси сущность PersonVM. Но при этом за командами будет обращаться к экземпляру MainVM в ресурсах App.
0
2298 / 1614 / 400
Регистрация: 26.06.2017
Сообщений: 4,780
Записей в блоге: 1
15.04.2025, 09:06  [ТС]
Элд Хасп, что-то реализация в ветке simple не работает, кнопка Save становится активной, но не нажимается. Да и ToolTip пустой зачем-то всплывает при этом.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,176
Записей в блоге: 2
15.04.2025, 11:07
Цитата Сообщение от Uswer Посмотреть сообщение
что-то реализация в ветке simple не работает, кнопка Save становится активной, но не нажимается. Да и ToolTip пустой зачем-то всплывает при этом.
Так...
Может в процессе объединения что-то потерял.
Проверю сейчас.

Добавлено через 8 минут
Отправил фиксацию.

Добавлено через 10 минут
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Желательно HasErrors прокидывать через INPC. Часто на это свойство завязывают какие-то триггера или привязки.
А без INPC они работать не будут.
Вот этого не было.
Правильная реализация RaiseErrorsChanged:
C#
83
84
85
86
87
        protected void RaiseErrorsChanged([CallerMemberName] string propertyName = null)
        {
            ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(propertyName));
            RaisePropertyChanged(nameof(HasErrors)); // Нужно обновить HasErrors
        }
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
15.04.2025, 11:07

Избежать одновременного выполнения LostFocus и команды кнопки MVVM
Помогите пожалуйста много об этом спрашивали, но ответа так и не нашла, может кто-то уже решил...

Кнопки в MVVM
Добрый день! У меня есть на View есть кнопка, которая должна просто открывать проводник. Код ее уже...

Не могу сделать отображение данных с кнопки и TextBox в MVVM
Не могу сделать отображение данных с помощью кнопки и TextBox. Только начал копаться в MVVM и хочу...

Добавление кнопки в форме с кнопки и смена фона новой кнопки
Хочу сделать так чтоб когда я запускал программу там было 2 кнопки, одна отвечала за создание новой...

Временное отключение валидации
&lt;asp:TextBox ID=&quot;FNBox&quot; runat=&quot;server&quot;&gt;&lt;/asp:TextBox&gt; &lt;asp:RequiredFieldValidator...


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

Или воспользуйтесь поиском по форуму:
72
Ответ Создать тему
Новые блоги и статьи
GitHub Copilot в JetBrains: модель по умолчанию, Fix и контроль MCP
and_y87 12.10.2026
10 октября 2026 года GitHub обновил Copilot для JetBrains: добавил настройки стартовой модели, исправления из диагностики и управление автозапуском MCP. Поддержка IDE 2025. 1 прекращена — требуется. . .
День 5 из 28: Codex подсказывает следующий запрос
and_y87 12.10.2026
9 октября 2026 года OpenAI запустила бету Composer predictions — подсказок следующего сообщения в текущем диалоге Codex. Это помощь с формулировкой запроса, а не автоматическое продолжение задачи. . . .
Запустил конкурс "тем и промптов для текстовых квестов созданных почти чисто ИИ"
Adler 06.10.2026
Всем привет! За последние три-четыре дня я создал более 16 текстовых квестовых игр используя преимущественно по одному запросу к ИИ на игру. Мне так понравилось смотреть все ветки/ сцены во всех. . .
ИИ не может найти нужный язык в списке
Supersumestria 05.10.2026
Я ему даю вот такое изображение и прошу найти и подчеркнуть немецкий язык. Возвращает он вот это: https:/ / i. **********/ vqBWLe2. png Нужную строчку в 3й колонке просто выдумал. . Это. . .
Новая последняя моя музыка в SUNO
zorxor 05.10.2026
Здравствуйте, дорогие мои друзья! С большой радостью я хотел бы представить вам свою новую последнею музыку, которую сгенерировала мне по моей просьбе нейросеть SUNO. С уважением, zorxor. Это. . .
Программный домашний кинотеатр
russiannick 27.09.2026
Сподобился на программный домашний кинотеатр. В качестве ЯВУ по традиции выбрал js. В помощники взял Яндекс-Алису. Было создано три зала на разные интересы. исторические и ретро сериал Хичкок. . .
Беседа с ИИ о программистах, недопускающих к созданию и правке кода генеративные ИИ и причины этого
zorxor 21.09.2026
Раньше я радовался или получал некоторые эмоции, пусть небольшие, но всё же, от самого процесса написания кода, рекомпиляции и запуска, видя постепенное развитие программы и прочее. А теперь лень. . .
Мобильное приложение ColorStep
pavlinmavlin 17.09.2026
Реализовал приложение Красный, Зеленый, Синий в Unity3d + c#. Название изменил на ColorStep. Приложение прошло модерацию и теперь доступно для скачивания. Делал его сам, шаг за шагом — и вот,. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru