Форум программистов, компьютерный форум, киберфорум
C#: WPF, UWP и Silverlight
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 5.00/11: Рейтинг темы: голосов - 11, средняя оценка - 5.00
172 / 118 / 57
Регистрация: 08.01.2013
Сообщений: 664

Включить кнопку, когда 3 TextBox заполнены

30.11.2019, 21:51. Показов 2349. Ответов 7
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Нашел 1 пример вроде бы короткий, но не могу разобраться.
Пример:
Кликните здесь для просмотра всего текста

Пример с использованием атрибутов и рефлексии.

Есть базовый класс для VM:
Кликните здесь для просмотра всего текста

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
abstract class Vm : INotifyPropertyChanged
{
    protected virtual bool Set<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
    {
        if (EqualityComparer<T>.Default.Equals(field, value))
            return false;
        field = value;
        NotifyPropertyChanged(propertyName);
        return true;
    }
 
    protected void NotifyPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
 
    public event PropertyChangedEventHandler PropertyChanged;
}

наследуем от него класс поддерживающий валидацию:
Кликните здесь для просмотра всего текста

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
abstract class ValidatableVm : Vm
{
    protected override bool Set<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
    {
        var b = base.Set(ref field, value, propertyName);
        if (b && GetType().GetProperty(propertyName).GetCustomAttributes(typeof(RequiredAttribute), true).Length > 0)
        {
            IsValid = GetType().GetProperties()
                               .Where(p => p.GetCustomAttributes(typeof(RequiredAttribute), true).Length > 0)
                               .Select(p => (string)p.GetValue(this))
                               .All(s => !string.IsNullOrEmpty(s));
            NotifyPropertyChanged(nameof(IsValid));
        }
        return b;
    }
 
    public bool IsValid { get; private set; }
}

Здесь в методе Set если произошло обновление свойства, то для текущего типа VM берем все свойства помеченные атрибутом и проверяем чтобы они были не пусты.
Я использовал атрибут Required из пространства имен System.ComponentModel.DataAnnotations, если вам это не подходит - вы можете создать свой атрибут.

Пример использования, VM:
Кликните здесь для просмотра всего текста

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class MainVM : ValidatableVm
{
    string name;
    [Required]
    public string Name
    {
        get => name;
        set => Set(ref name, value);
    }
 
    string address;
    [Required]
    public string Address
    {
        get => address;
        set => Set(ref address, value);
    }
 
    string phone;
    public string Phone
    {
        get => phone;
        set => Set(ref phone, value);
    }
}

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

Разметка:
XML
1
2
3
4
5
6
<StackPanel Margin="5">
    <TextBox Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}"/>
    <TextBox Text="{Binding Address, UpdateSourceTrigger=PropertyChanged}"/>
    <TextBox Text="{Binding Phone, UpdateSourceTrigger=PropertyChanged}"/>
    <Button Content="Click me" IsEnabled="{Binding IsValid}"/>
</StackPanel>


Вопросы:
1)"Есть базовый класс для VM:" Его нужно отдельно прописать или можно содержимое вписать в свой MainWindowViewModel?

2)Зачем это функция нужна, в чем его смысл?:
Кликните здесь для просмотра всего текста

C#
1
2
3
4
5
6
7
8
    protected virtual bool Set<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
    {
        if (EqualityComparer<T>.Default.Equals(field, value))
            return false;
        field = value;
        NotifyPropertyChanged(propertyName);
        return true;
    }

[CallerMemberName] что это и для чего нужен?

3)В переопределенном методе Set:
Кликните здесь для просмотра всего текста

C#
1
2
3
4
5
6
7
8
         if (b && GetType().GetProperty(propertyName).GetCustomAttributes(typeof(RequiredAttribute), true).Length > 0)
        {
            IsValid = GetType().GetProperties()
                               .Where(p => p.GetCustomAttributes(typeof(RequiredAttribute), true).Length > 0)
                               .Select(p => (string)p.GetValue(this))
                               .All(s => !string.IsNullOrEmpty(s));
            NotifyPropertyChanged(nameof(IsValid));
        }

Что значат эти записи подробно?

4)"Обратите внимание, атрибутом помечены только 2 свойства, именно они и будут проверяться на непустоту." Где эти 2 свойства?

Добавлено через 58 минут
Если Вам тоже сложно разобраться, можете предложить своё решение, которое соответствует архитектуре mvvm
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
30.11.2019, 21:51
Ответы с готовыми решениями:

Включить кнопку когда введен текст в два textbox
Хотелось бы узнать, как совершить данное действие: Есть 2 textbox'а и 1 button, нужно сделать так, чтобы пока не введены данные в 2...

Накапливать в textbox текст, когда нажимаешь кнопку
Ребята. Опять проблема. Хотел сделать 2 текстбокса и 1 кнопку. Идея такова, что в первый текстбокс вводишь данные, потом нажимаешь...

Числовые поля, их суммирование, когда не все заполнены
Здравствуйте ! У меня на форме 5 числовых полей. 1 для итога, 4 для подсчета. К примеру, если 3 поля заполнены числами, а 4 нет, то...

7
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16140 / 11264 / 2888
Регистрация: 21.04.2018
Сообщений: 33,109
Записей в блоге: 2
01.12.2019, 06:22
Цитата Сообщение от bloomder
1)"Есть базовый класс для VM:" Его нужно отдельно прописать или можно содержимое вписать в свой MainWindowViewModel?
Базовый класс создаётся, чтобы не делать каждый раз заново реализацию INPC.
Советую воспользоваться реализацией из поста Новая реализация OnPropertyChangedClass.

Тогда объявление свойств в VM предельно упростится
C#
1
2
3
4
5
public class CustomViewModel : OnPropertyChangedClass
{
      private int _number;
      public int Number { get => _number; set => SetProperty (ref _number, value); }
}
Также вы получаете возможность поместить всю логику свойств отдельно от их объявления (что в будущем значительно облегчает реализацию сложных решений) задав переопределение методов SetProperty и/или PropertyNewValue.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16140 / 11264 / 2888
Регистрация: 21.04.2018
Сообщений: 33,109
Записей в блоге: 2
01.12.2019, 06:30
Цитата Сообщение от bloomder
2)Зачем это функция нужна, в чем его смысл?
Проверяет при присвоении значения свойству равно ли оно текущему свойству.
И вызывает INPC только в случае их различий.
Это предотвращает излишние обновления Представления.
Для маленьких приложений это может быть не существо.
В больших имеет значение.
Лучше всегда делать так, что привыкнуть к правильной реализации.

В моём варианте это исполняет код методов
C#
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
        #region Виртуальные защищённые методы для изменения значений свойств
        /// <summary>Виртуальный метод определяющий изменения в значении поля значения свойства</summary>
        /// <param name="fieldProperty">Ссылка на поле значения свойства</param>
        /// <param name="newValue">Новое значение</param>
        /// <param name="propertyName">Название свойства</param>
        protected virtual void SetProperty<T>(ref T fieldProperty, T newValue, [CallerMemberName]string propertyName = "")
        {
            if ((fieldProperty != null && !fieldProperty.Equals(newValue)) || (fieldProperty == null && newValue != null))
                PropertyNewValue(ref fieldProperty, newValue, propertyName);
        }
 
        /// <summary>Виртуальный метод изменяющий значение поля значения свойства</summary>
        /// <param name="fieldProperty">Ссылка на поле значения свойства</param>
        /// <param name="newValue">Новое значение</param>
        /// <param name="propertyName">Название свойства</param>
        protected virtual void PropertyNewValue<T>(ref T fieldProperty, T newValue, string propertyName)
        {
            fieldProperty = newValue;
            OnPropertyChanged(propertyName);
        }
        #endregion
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16140 / 11264 / 2888
Регистрация: 21.04.2018
Сообщений: 33,109
Записей в блоге: 2
01.12.2019, 06:39
Цитата Сообщение от bloomder
3)В переопределенном методе Set
Получает все свойства, выбирает из них все строковые, проверяет все ли они заполнены.
Если все, то IsValid = true.

На мой взгляд через чур надуманно и практического смысла не имеет.
Такая логика даже не могу представить где может понадобиться.

Для валидации значений в Представление лучше использовать имеющийся механизм валидации.
В разделе есть несколько тем с его использованием.

Или в край, если нет желания вникать, делается уже в VM облачным образом и только для тех свойств чьи значения надо проверить, а не для всех строковых скопом.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16140 / 11264 / 2888
Регистрация: 21.04.2018
Сообщений: 33,109
Записей в блоге: 2
01.12.2019, 06:45
Цитата Сообщение от bloomder
4)"Обратите внимание, атрибутом помечены только 2 свойства, именно они и будут проверяться на непустоту." Где эти 2 свойства?
Поторопился в предыдущем посте.
Проверяются все свойства с указанными атрибутом.

Эти два свойства в Пример использования, VM:
Свойство Phone не будет проверяться.
Также не получится проверка не строковых свойств.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16140 / 11264 / 2888
Регистрация: 21.04.2018
Сообщений: 33,109
Записей в блоге: 2
01.12.2019, 07:18
Цитата Сообщение от bloomder
Если Вам тоже сложно разобраться, можете предложить своё решение, которое соответствует архитектуре mvvm
Сложно.
Так как сейчас в длительной поездке и до НГ без компа.
Но попробую объяснить со смарта.
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class CustomViewModel : OnPropertyChangedClass
{
      private int _age;
      public int Age { get => _age; set => SetProperty (ref _age, value); }
 
      private string _name;
      public int Name { get => _name; set => SetProperty (ref _name, value); }
 
      private DateTime? _birthday;
      public DateTime? Birthday { get => _birthday; set => SetProperty (ref _birthday, value); }
 
      public bool IsValid 
            => Age > 10 
                 && string.IsNullOrWhiteSpace(Name)
                 && Birthday != null && Birthday.Value >= new DateTime (1970,1,1);
 
     protected override void PropertyNewValue<T>(ref T fieldProperty, T newValue, string propertyName)
     {
           base.PropertyNewValue(ref fieldProperty, newValue, string propertyName);
           
          // Извещение о необходимости проверки валидации
          if ((new string []{nameof(Age), nameof(Name), nameof(Birthday)}).Contains(propertyName))
                OnPropertyChanged(nameof(IsValid));
     }
}
0
172 / 118 / 57
Регистрация: 08.01.2013
Сообщений: 664
20.12.2019, 01:30  [ТС]
Элд Хасп, IsValid как связан с PropertyNewValue?
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16140 / 11264 / 2888
Регистрация: 21.04.2018
Сообщений: 33,109
Записей в блоге: 2
20.12.2019, 07:25
bloomder, посмотрите реализацию OnPropertyChangedClass.

В базовом абсрактном классе классе OnPropertyChanged для присвоения значения свойству используется виртуальный метод SetProperty в который параметрами передаётся ссылка на поле хранящее значение свойства, новое значение свойства и имя свойства.
В методе проверяется эквивалентность текущего и нового значения. Если значение изменяется, то вызывается виртуальный метод PropertyNewValue с теми же параметрами.

В данном случае в переопределенном методе после присвоения значения проверяется какому из свойств было присвоено новее значении.
Если одному из string []{nameof(Age), nameof(Name), nameof(Birthday)}, то выдаётся оповещение о необходимости перепроверки значения свойства nameof(IsValid).

Добавлено через 19 минут
bloomder, для меня такая валидации в ViewModel гораздо понятнее, прозрачнее, гибче, чем использование атрибутов свойств.
Можно для валидации использовать любую функцию, любые типы.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
20.12.2019, 07:25
Помогаю со студенческими работами здесь

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

Перехват ошибки dataGridView когда заполнены не все поля строки
Я добавил на форму dataGridView и добавил через источник данных таблицу с тремя столбцами. Во всех столбцах запрещены Null значения. ...

Проверка что все textbox-ы заполнены
есть такая проблема. есть очень много текст боксов и всего другого. Нужно написать код в котором бы проверялось заполнены ли все...

Как разблокировать кнопку, если все текстбоксы заполнены?
нужно написать код, который возвращает button3.Enabled = true;, когда все текстбоксы заполнены. почему не работает?if (textBox1.Text==...

Выполнений функций в зависимости от того, заполнены ли textbox
Здравствуйте. Дано: 4 тексбокса, на основании заполнения 2-х из них разнообразными функциями будут заполнятся 2 оставшихся. Вопрос...


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

Или воспользуйтесь поиском по форуму:
8
Ответ Создать тему
Новые блоги и статьи
SDL3 для Desktop (MinGW): Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++
8Observer8 10.03.2026
Содержание блога Финальные проекты на Си и на C++: hello-sdl3-c. zip hello-sdl3-cpp. zip Результат:
Установка CMake и MinGW 13.1 для сборки С и C++ приложений из консоли и из Qt Creator в EXE
8Observer8 10.03.2026
Содержание блога MinGW - это коллекция инструментов для сборки приложений в EXE. CMake - это система сборки приложений. Здесь описаны базовые шаги для старта программирования с помощью CMake и. . .
Как дизайн сайта влияет на конверсию: 7 решений, которые реально повышают заявки
Neotwalker 08.03.2026
Многие до сих пор воспринимают дизайн сайта как “красивую оболочку”. На практике всё иначе: дизайн напрямую влияет на то, оставит человек заявку или уйдёт через несколько секунд. Даже если у вас. . .
Модульная разработка через nuget packages
DevAlt 07.03.2026
Сложившийся в . Net-среде способ разработки чаще всего предполагает монорепозиторий в котором находятся все исходники. При создании нового решения, мы просто добавляем нужные проекты и имеем. . .
Модульный подход на примере F#
DevAlt 06.03.2026
В блоге дяди Боба наткнулся на такое определение: В этой книге («Подход, основанный на вариантах использования») Ивар утверждает, что архитектура программного обеспечения — это структуры,. . .
Управление камерой с помощью скрипта OrbitControls.js на Three.js: Вращение, зум и панорамирование
8Observer8 05.03.2026
Содержание блога Финальная демка в браузере работает на Desktop и мобильных браузерах. Итоговый код: orbit-controls-threejs-js. zip. Сканируйте QR-код на мобильном. Вращайте камеру одним пальцем,. . .
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip Сканируйте QR-код на мобильном и вы увидите, что появится джойстик для управления главным героем. . . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru