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

Обработка ввода не числового значения с соблюдением MVVM

11.07.2025, 19:05. Показов 1140. Ответов 13

Студворк — интернет-сервис помощи студентам
Хочу сделать так, чтобы при вводе в текстовое поле не цифр или числа, не попадающего в диапазон от 0 до 100, кнопка становилась недоступной. Второй пункт успешно выполнен, но с реализацией первого проблемы: если поставить точку останова на строчку cost = value и ввести в поле букву, то можно увидеть, что программа не доходит до этой строки.

MainWindow.xaml
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<Window x:Class="WpfApp2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp2"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <StackPanel Orientation="Vertical" VerticalAlignment="Center">
            <TextBox Width="100" Height="30">
                <TextBox.Text>
                    <Binding Path="Cost" UpdateSourceTrigger = "PropertyChanged"  ValidatesOnExceptions = "True" StringFormat = "{}{0:F3}">
                        <Binding.ValidationRules>
                            <DataErrorValidationRule />
                        </Binding.ValidationRules>
                    </Binding>
                </TextBox.Text>
            </TextBox>
            <Button  Width="120" Height="20" IsEnabled="{Binding IsAcceptEnable}">Подтвердить ввод</Button>
        </StackPanel>
    </Grid>
</Window>

MainWindow.xaml.cs
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
using System.Windows;
 
namespace WpfApp2
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
 
 
            DataContext = new ViewModel();
        }
    }
}

ViewModel.cs
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
using System.ComponentModel;
using System.Runtime.CompilerServices;
 
namespace WpfApp2
{
    internal class ViewModel : INotifyPropertyChanged, IDataErrorInfo
    {
        public string this[string columnName]
        {
            get
            {
                string error = String.Empty;
                switch (columnName)
                {
                    case nameof(Cost):
                        if ((Cost < 0) || (Cost > 100))
                        {
                            error = "Цена должна быть больше 0 и меньше 100";
                        }
                        break;
                }
 
                if (error != String.Empty)
                {
                    IsAcceptEnable = false;
                }
                else
                {
                    IsAcceptEnable = true;
                }
 
                return error;
            }
        }
 
        private double cost;
        public double Cost
        {
            get => cost;
 
            set
            {
                cost = value;
 
                OnPropertyChanged();
            }
        }
 
        private bool isAcceptEnable;
        public bool IsAcceptEnable
        {
            get
            {
                return isAcceptEnable;
            }
            private set
            {
                isAcceptEnable = value;
 
                OnPropertyChanged();
            }
        }
 
 
        public string Error => throw new NotImplementedException();
 
        public event PropertyChangedEventHandler PropertyChanged;
        public void OnPropertyChanged([CallerMemberName] string prop = "")
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(prop));
        }
    }
}
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
11.07.2025, 19:05
Ответы с готовыми решениями:

Проблемы с анимацией RadioButton на главной форме с соблюдением MVVM
На моей главной форме есть колонка с RadioButton и я хотел сделать так что бы по нажатию по разделу...

Совместить изображения с соблюдением Альфа канала
Как совместить изображения соблюдая альфа канал???

Объединение массивов с соблюдением упорядоченности
1) Даны два массива A и B, элементы которых упорядочены по возрастанию. 2) Объединить эти массивы...

13
Эксперт JavaЭксперт по электроникеЭксперт .NET
 Аватар для wizard41
3376 / 2678 / 573
Регистрация: 04.09.2018
Сообщений: 8,492
Записей в блоге: 3
11.07.2025, 19:46
Цитата Сообщение от Oleg Shamanikov Посмотреть сообщение
программа не доходит до этой строки
Срабатывает стандартный валидатор. Если поле ввода привязано к числовому свойству, то свойство не установится если там НЕ число.
0
1 / 1 / 1
Регистрация: 27.05.2022
Сообщений: 168
11.07.2025, 20:33  [ТС]
Я это понимаю, но есть ли способ обойти это?
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16113 / 11234 / 2887
Регистрация: 21.04.2018
Сообщений: 33,035
Записей в блоге: 2
11.07.2025, 20:49
Цитата Сообщение от wizard41 Посмотреть сообщение
Цитата Сообщение от Oleg Shamanikov Посмотреть сообщение
чтобы при вводе в текстовое поле не цифр или числа, не попадающего в диапазон от 0 до 100, кнопка становилась недоступной... программа не доходит до этой строки
Цитата Сообщение от wizard41 Посмотреть сообщение
программа не доходит до этой строки
Срабатывает стандартный валидатор. Если поле ввода привязано к числовому свойству, то свойство не установится если там НЕ число.
Oleg Shamanikov, есть две немного разные задачи.
1) Ввод только числовых значений в свойство-источник. Это "стандартный" подход в WPF, о чем и написал вам wizard41. В этом случае валидация в VM сводится только к валидации самого уже полученного численного значения.
2) Полная валидация текстового поля в ViewModel. Это возможно, то что вы имели ввиду. В этом случае в VM нужно тестовое свойство. Его сначала нужно конвертировать в численное. Если не возможно, то выдать ошибку валидации для конвертации. А потом уже проверить на диапазон и выдавать такую ошибку.


P.S.
1) Советую использовать базовую реализацию INPC, а не каждый раз "с нуля" её делать. Для примера можете взять отсюда: Простые реализации для тем на форуме

2) Вместо IDataErrorInfo лучше применять INotifyDataErrorInfo

3) Задавать контекст данных лучше в XAML. Это можно сделать несколькими различными способами. Даже в сложных случаях, когда такое невозможно, надо задать хотя бы контекст данных времени разработки.
0
Эксперт JavaЭксперт по электроникеЭксперт .NET
 Аватар для wizard41
3376 / 2678 / 573
Регистрация: 04.09.2018
Сообщений: 8,492
Записей в блоге: 3
11.07.2025, 21:11
Цитата Сообщение от Oleg Shamanikov Посмотреть сообщение
есть ли способ обойти это?
обойти? что именно?
Либо вводится число и затем происходит проверка диапазона, либо вводиться не число и оно отклоняется еще на уровне View. Можно конкретно написать свой валидатор и в нем прописать свою логику реагирования на то или иное.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16113 / 11234 / 2887
Регистрация: 21.04.2018
Сообщений: 33,035
Записей в блоге: 2
11.07.2025, 21:41
Цитата Сообщение от Oleg Shamanikov Посмотреть сообщение
Я это понимаю, но есть ли способ обойти это?
Вариант реализации (не тестировал - могут быть ошибки):

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
    public class ValidateNumberViewModel : BaseInpc, INotifyDataErrorInfo
    {
        private decimal _cost;
        public decimal Cost { get => _cost; private set => Set(ref _cost, value); }
        private string? _costText;
        public string? CostText { get => _costText; set => Set(ref _costText, value); }
 
        private bool _isAcceptEnable;
 
        public event EventHandler<DataErrorsChangedEventArgs>? ErrorsChanged;
 
        public bool IsAcceptEnable { get => _isAcceptEnable; set => Set(ref _isAcceptEnable, value); }
        public bool HasErrors => !(string.IsNullOrWhiteSpace(costTextError) && string.IsNullOrWhiteSpace(costError));
 
        public IEnumerable GetErrors(string? propertyName)
        {
            if (propertyName is nameof(CostText))
            {
                if (!string.IsNullOrWhiteSpace(costTextError))
                    yield return costTextError;
                if (!string.IsNullOrWhiteSpace(costError))
                    yield return costError;
            }
            else if (propertyName is nameof(Cost))
            {
                if (!string.IsNullOrWhiteSpace(costError))
                    yield return costError;
            }
            else if (string.IsNullOrEmpty(propertyName))
            {
                if (!string.IsNullOrWhiteSpace(costTextError))
                    yield return $"{nameof(CostText)}: {costTextError}";
                if (!string.IsNullOrWhiteSpace(costError))
                    yield return $"{nameof(CostText)}: {costError}";
            }
        }
 
        public string? costTextError;
        private string? costError;
 
        protected override void OnPropertyChanged(in string propertyName, in object? oldValue, in object? newValue)
        {
            base.OnPropertyChanged(propertyName, oldValue, newValue);
 
            if (propertyName is nameof(CostText))
            {
                if (decimal.TryParse(CostText, CultureInfo.InvariantCulture, out decimal cost))
                {
                    costTextError = null;
                }
                else
                {
                    costTextError = "Значение нельзя перевести в число.";
                }
                RaisePropertyChanged(nameof(HasErrors));
                ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(nameof(CostText)));
 
                if (costTextError is null)
                {
                    Cost = cost;
                }
            }
            else if (propertyName is nameof(Cost))
            {
                var cost = Cost;
                if (cost < 0 || cost > 100)
                {
                    costError = "Цена должна быть больше 0 и меньше 100";
                }
                else
                {
                    costError = null;
                }
                RaisePropertyChanged(nameof(HasErrors));
                ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(nameof(CostText)));
                ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(nameof(Cost)));
            }
        }
    }
0
2277 / 1594 / 399
Регистрация: 26.06.2017
Сообщений: 4,716
Записей в блоге: 1
17.07.2025, 06:21
Мне кажется, что задачу можно и нужно решить на уровне View.
Кликните здесь для просмотра всего текста
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<Window x:Class="WpfApp2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp2"
        xmlns:r="clr-namespace:WpfApp2.ValidationRules"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <StackPanel Orientation="Vertical" VerticalAlignment="Center">
            <TextBox Width="100" Height="30">
                <TextBox.Text>
                    <Binding Path="Cost" UpdateSourceTrigger = "PropertyChanged" StringFormat = "{}{0:F3}">
                        <Binding.ValidationRules>
                               <r:CostRule Min="0" Max ="100"/>
                        </Binding.ValidationRules>
                    </Binding>
                </TextBox.Text>
            </TextBox>
            <Button  Width="120" Height="20">Подтвердить ввод</Button>
        </StackPanel>
    </Grid>
</Window>


Правило.
Кликните здесь для просмотра всего текста
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
26
27
28
29
30
31
32
33
34
35
36
using System;
using System.Globalization;
using System.Windows.Controls;
 
namespace WpfApp2.ValidationRules
{
  public class CostRule : ValidationRule
  {
    public int Min { get; set; }
    public int Max { get; set; }
 
    public CostRule() { }
 
    public override ValidationResult Validate(object value, CultureInfo cultureInfo)
    {
      int interval = 0;
 
      try
      {
        if (((string)value).Length > 0)
          interval = Int32.Parse((string)value);
      }
      catch(Exception ex)
      {
        return new ValidationResult(false, ex.Message);
      }
 
      if ((interval < Min)||(interval > Max))
      {
        return new ValidationResult(false, $"Значение выходит за допустимые пределы: {Min} - {Max}.");
      }
 
      return ValidationResult.ValidResult;
    }
  }
}


моделька
Кликните здесь для просмотра всего текста
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
26
27
28
using System.ComponentModel;
using System.Runtime.CompilerServices;
 
namespace WpfApp2
{
    internal class ViewModel : INotifyPropertyChanged
    {
        private double cost;
        public double Cost
        {
            get => cost;
 
            set
            {
                cost = value;
 
                OnPropertyChanged();
            }
        }
 
        public event PropertyChangedEventHandler PropertyChanged;
        public void OnPropertyChanged([CallerMemberName] string prop = "")
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(prop));
        }
    }
}


P.S. Есть одно НО, то самое, с которым я тоже в своё время боролся - это кнопка. Проблема в том, что VM всегда "видит" только валидную модель, поэтому просемафирить кнопке можно только реализуя проверку на уровне VM. Как сделать проверку на уровне VM Элд Хасп уже написал, остаётся только кнопке указать команду и для неё наложить ограничение CanExecute.

Добавлено через 4 минуты
Кстати, Элд Хасп, подскажи как прямо во вью проверить состояние валидации поля Cost, чтобы установить у кнопки, например тот же IsEnabled="{Binding чего-то там}".
0
 Аватар для Andrey-MSK
3308 / 2196 / 386
Регистрация: 14.08.2018
Сообщений: 7,387
Записей в блоге: 4
17.07.2025, 08:36
Цитата Сообщение от Uswer Посмотреть сообщение
чтобы установить у кнопки, например тот же IsEnabled="{Binding чего-то там}"
А зачем, если для кнопки есть
Цитата Сообщение от Uswer Посмотреть сообщение
остаётся только кнопке указать команду и для неё наложить ограничение CanExecute.
?
CanExecute() сам включит/отключит кнопку.
0
2277 / 1594 / 399
Регистрация: 26.06.2017
Сообщений: 4,716
Записей в блоге: 1
17.07.2025, 09:08
Цитата Сообщение от Andrey-MSK Посмотреть сообщение
включит/отключит кнопку
Это да, но оно же в VM, а валидация не выходит за пределы View, поэтому и требуется там же (во View) блокировать кнопку.
0
 Аватар для Andrey-MSK
3308 / 2196 / 386
Регистрация: 14.08.2018
Сообщений: 7,387
Записей в блоге: 4
17.07.2025, 09:34
Цитата Сообщение от Uswer Посмотреть сообщение
а валидация не выходит за пределы View
А что мешает валидацию сделать в VM, ведь именно она готовит данные для модели и передаёт в неё уже полностью готовые для использования.
Цитата Сообщение от Uswer Посмотреть сообщение
XML
1
<Binding Path="Cost" UpdateSourceTrigger = "PropertyChanged" StringFormat = "{}{0:F3}">
Вот тут как раз триггер с таким значением для этого и используется. Единственное замечание, для значений чисел с плавающей точкой в TextBox, для проектов на NET 6+ WPF, нужно в конструктор App добавить вот это
C#
1
2
3
4
5
6
7
8
9
10
11
public App()
{
    // Данная опция позволяет использовать тип обновления привязки UpdateSourceTrigger=PropertyChanged
    // для TextBox при вводе дробных значений.
    FrameworkCompatibilityPreferences.KeepTextBoxDisplaySynchronizedWithTextProperty = false;
 
    Configuration = GetConfiguration();
    Services = ConfigureServices();
 
    InitializeComponent();
}
В NET Framewok эта опция по умолчанию выключена, а вот в NET 6+ её зачем-то решили включить...

Добавлено через 17 минут
Цитата Сообщение от Uswer Посмотреть сообщение
поэтому и требуется там же (во View) блокировать кнопку
И если на кнопку будет повешены и CanExecute(), и IsEnabled, то при смене этих условий она будет моргать, а это не оченно хорошо выглядит. Так что нужно выбирать что-то одно... И лучше пусть это будет CanExecute()
0
2277 / 1594 / 399
Регистрация: 26.06.2017
Сообщений: 4,716
Записей в блоге: 1
17.07.2025, 10:23
Цитата Сообщение от Andrey-MSK Посмотреть сообщение
А что мешает валидацию сделать в VM
Andrey-MSK, ну я не знаю как ещё объяснить. Мир не черно-белый, вы делаете строго по букварю (ни ни шагнуть в сторону от паттерна), а другие делают иначе. Ну вот, допустим, припёрло кому-то валидировать значение не выходя за View. Чего в этом плохого? Мало того, биндинги сами к этому подталкивают. И вот в этом случае надо организовать взаимосвязь элементов View. Лично мне такое взаимодействие кажется очень логичным. Основная задача VM связать View с моделью, и да VM может заниматься той же валидацией, но тогда только она это должна делать. А проблема в том, что во View наглухо имплантирована некоторая часть валидации. Вопрос этой темы как раз об этом.
Если подумать, то возникает вопрос "зачем вообще во View вшита валидация?" Ответ в общем-то тоже понятен - для упрощения разработки. Проблема в том, что WPF не разрабатывалась под паттерн MVVM, а как раз наоборот. Отсюда и вот такие коллизии возникают.
0
 Аватар для Andrey-MSK
3308 / 2196 / 386
Регистрация: 14.08.2018
Сообщений: 7,387
Записей в блоге: 4
17.07.2025, 10:43
Uswer, Если почитать книгу по привязкам в формах, то там вообще валидация делается в модели. Я к чему это всё... Вы ведь сами писали про CanExecute() на кнопке - ведь именно он разрешает выполнение команды. Некорректные данные при вводе (UpdateSourceTrigger="PropertyChanged" обновляет свойство на лету, при вводе) - команда не доступна, свойство выдаёт ошибку валидации при вводе - красная рамка с подсказкой, откуда прилетит IDataErrorInfo не важно, свойство прошло -> CanExecute() сработал -> команда выполнилась.
И вот это замечание тоже важно
Цитата Сообщение от Andrey-MSK Посмотреть сообщение
И если на кнопку будет повешены и CanExecute(), и IsEnabled, то при смене этих условий она будет моргать, а это не оченно хорошо выглядит.
Было у меня в нескольких местах так и я понять не мог из-за чего оно моргает. Потом убрал везде IsEnabled и всё стало чики-пуки
0
2277 / 1594 / 399
Регистрация: 26.06.2017
Сообщений: 4,716
Записей в блоге: 1
17.07.2025, 11:02
Andrey-MSK, наверное я плохо излагаю, моя вина. В ответе я указал сразу на два возможных решения. Первое то, что указано кодом, а второе в P.S. И этим я всех запутал. В моей голове это два независимых варианта: либо валидация только во View, либо в VM через INotifyDataErrorInfo.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16113 / 11234 / 2887
Регистрация: 21.04.2018
Сообщений: 33,035
Записей в блоге: 2
17.07.2025, 23:51
Цитата Сообщение от Uswer Посмотреть сообщение
одскажи как прямо во вью проверить состояние валидации поля Cost, чтобы установить у кнопки, например тот же IsEnabled="{Binding чего-то там}".
По реализации ничего сложного. Вы сами написали один из вариантов решения: привязка через конвертер.

Здесь вопрос больше по разделению функционала: должен это делать именно View, а не ViewModel? Кнопка выполняет действие уровня VM или Модели? Такая валидация это ограничение GUI (View) или Бизнес-Логики (Model)?

ТС предоставил очень мало информации. Фактически он описал не "что нужно сделать", а "как он хочет сделать". Поэтому дать верный во всех смыслах ответ невозможно.

ТС хочет свою кастомную валидацию даже приведения строки к числу.
На мой взгляд, ограничение диапазона Cost - это ответственность Модели (она может её делегировать VM).
Но вот приведение строки к числу -это ответственность View.
Что мы получаем в итоге.
Состояние команды зависит от валидации диапазона Cost, но у команды нет информации о валидации приведения строки к числу.
Поэтому может получиться, что Юзер ввел неверное значение, при этом в свойстве VM Cost валидное по диапазону значение. Но пользователь его не видит и кнопка при этом активна, так как команда в VM валидна.

Как с этим бороться.
По сути два варианта:
1) Дополнительно через IsEnabled кнопки отключать её, если есть ошибки в GUI. Например можно использовать для агрегации всех ошибок такое решение: Как получить ошибки валидации от всех дочерних элементов [WPF, Элд Хасп]
2) Создать сложный аргумент команды и прокидывать через него в команду из View нужные зависимости.

Я лично предпочитаю второй вариант. Это упрощает понимание кода, вся валидации происходит в одном месте - в команде VM.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
17.07.2025, 23:51
Помогаю со студенческими работами здесь

Справочник с соблюдением принципов ООП
Доброго времени суток! Имеются классы: namespace Spravochnik { public class User ...

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

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

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

Как добавлять данные в DataGrid через Textbox со связкой с SQLite при соблюдении MVVM ?
Здравствуйте! Подскажите пожалуйста. Изучаю WPF и совместно пытаюсь понять, как работать с...


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

Или воспользуйтесь поиском по форуму:
14
Ответ Создать тему
Новые блоги и статьи
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
Фото: Daniel Greenwood
kumehtar 13.11.2025
Расскажи мне о Мире, бродяга
kumehtar 12.11.2025
— Расскажи мне о Мире, бродяга, Ты же видел моря и метели. Как сменялись короны и стяги, Как эпохи стрелою летели. - Этот мир — это крылья и горы, Снег и пламя, любовь и тревоги, И бескрайние. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru