/
d4nil
/
Konenkov_2413_software_engineering_
Обзор
Документация
Войти
/
d4nil
/
Konenkov_2413_software_engineering_
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
main
ProgressMonitor/ProgressWindowViewModel.cs
302 строки
8 KB
Konenkov Daniel
doc: добавить комментарии
10 дек 2025, 16:37
10 дек 2025, 16:37
c99fbd9
Код
Авторство
О чём код?
using System.Collections.Generic; using System.ComponentModel; using System.Runtime.CompilerServices; using System.Windows.Input; namespace ProgressMonitor; /// <summary> /// ViewModel окна прогресса. /// </summary> public class ProgressWindowViewModel : INotifyPropertyChanged { /// <summary> /// Текущий заголовок окна. /// </summary> private string _title = string.Empty; /// <summary> /// Основной текстовое описание. /// </summary> private string _caption = string.Empty; /// <summary> /// Дополнительная подпись. /// </summary> private string _subtitle = string.Empty; /// <summary> /// Максимальное значение прогресса. /// </summary> private double _maxProgress = 1; /// <summary> /// Текущее значение прогресса. /// </summary> private double _currentProgress; /// <summary> /// Текстовое представление прогресса. /// </summary> private string _progressSummary = "0 / 1"; /// <summary> /// Подпись на кнопке отмены/закрытия. /// </summary> private string _cancelButtonText = "Отмена"; /// <summary> /// Признак доступности кнопки отмены. /// </summary> private bool _isCancelEnabled = true; /// <summary> /// Признак того, что пользователь запросил отмену. /// </summary> private bool _isCancellationRequested; /// <summary> /// Флаг завершения операции. /// </summary> private bool _isCompleted; /// <summary> /// Инициализирует ViewModel окна прогресса. /// </summary> public ProgressWindowViewModel() { CancelCommand = new RelayCommand(_ => RequestCancellation(), _ => IsCancelEnabled); } public event PropertyChangedEventHandler? PropertyChanged; /// <summary> /// Заголовок окна. /// </summary> public string Title { get => _title; set => SetField(ref _title, value); } /// <summary> /// Основной текст. /// </summary> public string Caption { get => _caption; set => SetField(ref _caption, value); } /// <summary> /// Дополнительная подпись. /// </summary> public string Subtitle { get => _subtitle; set => SetField(ref _subtitle, value); } /// <summary> /// Максимальное значение прогресса. /// </summary> public double MaxProgress { get => _maxProgress; set { var clamped = Math.Max(1, value); if (SetField(ref _maxProgress, clamped)) { ClampProgress(); UpdateSummary(); } } } /// <summary> /// Текущее значение прогресса. /// </summary> public double CurrentProgress { get => _currentProgress; set { var clamped = Math.Clamp(value, 0, MaxProgress); if (SetField(ref _currentProgress, clamped)) { UpdateSummary(); } } } /// <summary> /// Отображение прогресса в виде строки. /// </summary> public string ProgressSummary { get => _progressSummary; private set => SetField(ref _progressSummary, value); } /// <summary> /// Текст на кнопке отмены/закрытия. /// </summary> public string CancelButtonText { get => _cancelButtonText; private set => SetField(ref _cancelButtonText, value); } /// <summary> /// Доступность кнопки отмены. /// </summary> public bool IsCancelEnabled { get => _isCancelEnabled; private set { if (SetField(ref _isCancelEnabled, value)) { (CancelCommand as RelayCommand)?.RaiseCanExecuteChanged(); } } } /// <summary> /// Признак запроса отмены. /// </summary> public bool IsCancellationRequested { get => _isCancellationRequested; private set => SetField(ref _isCancellationRequested, value); } /// <summary> /// Команда отмены. /// </summary> public ICommand CancelCommand { get; } /// <summary> /// Событие, возникающее при запросе отмены. /// </summary> public event EventHandler? CancelRequested; /// <summary> /// Событие, возникающее при запросе закрытия. /// </summary> public event EventHandler? CloseRequested; /// <summary> /// Обновляет прогресс и подпись. /// </summary> /// <param name="parStep">Приращение прогресса.</param> /// <param name="parSubtitle">Новый подзаголовок.</param> public void UpdateProgress(double parStep = 1, string? parSubtitle = null) { CurrentProgress += parStep; if (!string.IsNullOrWhiteSpace(parSubtitle)) { Subtitle = parSubtitle!; } } /// <summary> /// Сброс кнопки в состояние отмены. /// </summary> public void ResetButtonState() { _isCompleted = false; CancelButtonText = "Отмена"; IsCancellationRequested = false; IsCancelEnabled = true; } /// <summary> /// Перевод кнопки в состояние завершения. /// </summary> public void SwitchToCompletionState() { _isCompleted = true; CancelButtonText = "Закрыть"; IsCancelEnabled = true; CloseRequested?.Invoke(this, EventArgs.Empty); } /// <summary> /// Отключает кнопку отмены, если нужно дождаться завершения операции. /// </summary> public void DisableCancellationButton() { IsCancelEnabled = false; } /// <summary> /// Обрабатывает пользовательский запрос на отмену либо закрытие. /// </summary> private void RequestCancellation() { if (_isCompleted) { CloseRequested?.Invoke(this, EventArgs.Empty); return; } if (IsCancellationRequested) { return; } IsCancellationRequested = true; IsCancelEnabled = false; CancelRequested?.Invoke(this, EventArgs.Empty); } /// <summary> /// Ограничивает текущий прогресс значением из допустимого диапазона. /// </summary> private void ClampProgress() { if (_currentProgress > MaxProgress) { _currentProgress = MaxProgress; OnPropertyChanged(nameof(CurrentProgress)); } } /// <summary> /// Пересчитывает строковое представление прогресса. /// </summary> private void UpdateSummary() { ProgressSummary = $"{CurrentProgress:N0} / {MaxProgress:N0}"; } /// <summary> /// Универсальный сеттер, уведомляющий интерфейс при изменении значения. /// </summary> /// <param name="parField">Ссылка на изменяемое поле.</param> /// <param name="parValue">Новое значение.</param> /// <param name="parPropertyName">Имя свойства, использующего поле.</param> /// <typeparam name="T">Тип значения.</typeparam> private bool SetField<T>(ref T parField, T parValue, [CallerMemberName] string? parPropertyName = null) { if (EqualityComparer<T>.Default.Equals(parField, parValue)) { return false; } parField = parValue; OnPropertyChanged(parPropertyName); return true; } /// <summary> /// Уведомляет подписчиков об изменении указанного свойства. /// </summary> /// <param name="parPropertyName">Имя изменившегося свойства.</param> private void OnPropertyChanged(string? parPropertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(parPropertyName)); } }