/
dOJer113
/
Insect
Обзор
Документация
Войти
/
dOJer113
/
Insect
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
server
ProgressOverlayWindow/Views/ProgressOverlayWindow.axaml.cs
143 строки
4 KB
aleks
lab 5
14 дек 2025, 19:32
14 дек 2025, 19:32
395af5a
Код
Авторство
О чём код?
using System; using System.Threading; using System.Threading.Tasks; using Avalonia.Controls; using Avalonia.Interactivity; using Avalonia.Threading; using ProgressOverlayWindow.ViewModels; namespace ProgressOverlayWindow.Views; /// <summary> /// Окно отображения прогресса выполнения длительных операций. /// </summary> public partial class ProgressOverlayWindow : Window, IProgressOverlayWindow { private readonly ProgressOverlayViewModel _viewModel; private readonly TimeSpan _minVisible = TimeSpan.FromMilliseconds(500); private CancellationTokenSource? _cts; private Task? _operationTask; private DateTimeOffset _openedAt = DateTimeOffset.UtcNow; /// <summary> /// Создает окно прогресса. /// </summary> public ProgressOverlayWindow() { InitializeComponent(); _viewModel = new ProgressOverlayViewModel(); DataContext = _viewModel; _viewModel.CancelRequested += OnCancelRequested; _viewModel.CloseRequested += OnCloseRequested; Opened += OnOpened; Closing += OnClosing; } /// <summary> /// Запускает задачу с отображением прогресса. /// </summary> /// <param name="parOperation">Делегат операции.</param> /// <param name="parOwner">Родительское окно.</param> /// <param name="parExternalCancellation">Токен отмены.</param> public async Task RunAsync( Func<IProgressOverlayWindow, CancellationToken, Task> parOperation, Window parOwner, CancellationToken parExternalCancellation) { _cts = CancellationTokenSource.CreateLinkedTokenSource(parExternalCancellation); _viewModel.ResetButtonState(); _operationTask = ExecuteOperationAsync(parOperation, _cts.Token); var dialogTask = ShowDialog(parOwner); await Task.WhenAll(_operationTask, dialogTask); } /// <inheritdoc /> public void Initialize(string parTitle, string parCaption, string? parSubtitle, double parMaxProgress) { Dispatcher.UIThread.Post(() => { _viewModel.Initialize(parTitle, parCaption, parSubtitle, parMaxProgress); Title = parTitle; }); } /// <inheritdoc /> public void NextStep(double parStep = 1, string? parSubtitle = null) { Dispatcher.UIThread.Post(() => _viewModel.UpdateProgress(parStep, parSubtitle)); } /// <inheritdoc /> public void Close(bool parAutoCloseWindow = true) { _ = FinishAsync(parAutoCloseWindow); } private async Task FinishAsync(bool parAutoCloseWindow) { await Dispatcher.UIThread.InvokeAsync(_viewModel.SwitchToCompletionState); if (!parAutoCloseWindow) { return; } var elapsed = DateTimeOffset.UtcNow - _openedAt; if (elapsed < _minVisible) { await Task.Delay(_minVisible - elapsed); } await Dispatcher.UIThread.InvokeAsync(Close); } private void OnOpened(object? parSender, EventArgs parArgs) { _openedAt = DateTimeOffset.UtcNow; } private void OnClosing(object? parSender, WindowClosingEventArgs parArgs) { if (_viewModel.IsCompleted || (_cts?.IsCancellationRequested ?? false)) { return; } parArgs.Cancel = true; _viewModel.DisableCancellation(); _cts?.Cancel(); } private void OnCancelRequested(object? parSender, EventArgs parArgs) { _viewModel.DisableCancellation(); _cts?.Cancel(); } private void OnCloseRequested(object? parSender, EventArgs parArgs) { Close(); } private async Task ExecuteOperationAsync( Func<IProgressOverlayWindow, CancellationToken, Task> parOperation, CancellationToken parToken) { try { await parOperation(this, parToken); } catch (OperationCanceledException) { await Dispatcher.UIThread.InvokeAsync(() => _viewModel.UpdateSubtitle("Операция отменена")); Close(); throw; } catch (Exception ex) { await Dispatcher.UIThread.InvokeAsync(() => _viewModel.UpdateSubtitle($"Ошибка: {ex.Message}")); Close(); throw; } } }