1
0
This commit is contained in:
2024-09-11 20:21:01 +03:00
parent d11a80b884
commit 8675b316b5
8 changed files with 362 additions and 59 deletions

View File

@@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<UseWPF>true</UseWPF>
<RootNamespace>ProgressWindow</RootNamespace>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,19 @@
<Window x:Class="ProgressWindow.ProgressBarWindow"
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"
mc:Ignorable="d"
Title="Title" Height="200" Width="400" Closing="Window_Closing">
<Grid>
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="0,0,0,10">
<TextBlock x:Name="_messageTextBlock" Text="Message" FontSize="16" Margin="0,0,0,0" />
</StackPanel>
<ProgressBar x:Name="_progressBar" Width="300" Height="30" />
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="0,10,0,0">
<Button x:Name="_cancelButton" Content="Cancel" Width="100" Height="30" Click="CancelButton_Click" />
</StackPanel>
</StackPanel>
</Grid>
</Window>

View File

@@ -0,0 +1,135 @@
using System;
using System.ComponentModel;
using System.Windows;
namespace ProgressWindow;
/// <summary>
/// Interaction logic for ProgressBar.xaml
/// </summary>
public partial class ProgressBarWindow : Window
{
/// <summary>
/// Событие, вызываемое при отмене задачи.
/// </summary>
public event EventHandler? Cancelled;
/// <summary>
/// Объект для синхронизации доступа к переменным.
/// </summary>
private readonly object _lock = new();
/// <summary>
/// Флаг, указывающий, нужно ли автоматически закрывать окно по завершении задачи.
/// </summary>
private readonly bool _autoClose;
/// <summary>
/// Максимальное значение прогресса.
/// </summary>
private readonly int _maxProgress;
/// <summary>
/// Текущее значение прогресса.
/// </summary>
private int _progress = 0;
/// <summary>
/// Флаг, указывающий, была ли задача отменена.
/// </summary>
private bool _isCancelled = false;
/// <summary>
/// Флаг, указывающий, завершена ли задача.
/// </summary>
private bool _isCompleted = false;
/// <summary>
/// Конструктор для инициализации окна прогресса.
/// </summary>
/// <param name="parTitle">Заголовок окна.</param>
/// <param name="parInitialMessage">Начальное сообщение для отображения.</param>
/// <param name="parMaxProgress">Максимальное значение прогресса.</param>
/// <param name="parAutoClose">Флаг, указывающий, должно ли окно закрываться автоматически по завершении.</param>
public ProgressBarWindow(string parTitle, string parInitialMessage, int parMaxProgress, bool parAutoClose = true)
{
InitializeComponent();
Title = parTitle;
_messageTextBlock.Text = parInitialMessage;
_maxProgress = parMaxProgress;
_autoClose = parAutoClose;
}
/// <summary>
/// Увеличивает текущий прогресс на указанную величину и обновляет сообщение, если предоставлено.
/// </summary>
/// <param name="parIncrement">Количество единиц, на которое нужно увеличить прогресс.</param>
/// <param name="parMessage">Сообщение для отображения в окне (опционально).</param>
/// <returns>Возвращает true, если задача была отменена.</returns>
public bool AdvanceProgress(int parIncrement = 1, string? parMessage = null)
{
lock (_lock)
{
_progress += parIncrement;
if (_progress >= _maxProgress)
{
_progress = _maxProgress;
_isCompleted = true;
_cancelButton.Content = "Close";
}
if (parMessage != null)
_messageTextBlock.Text = parMessage;
_progressBar.Value = (double)_progress / (double)_maxProgress * 100;
_progressBar.ToolTip = $"{_progress}/{_maxProgress} {parMessage}";
if (_isCompleted && _autoClose)
Close();
}
return _isCancelled;
}
/// <summary>
/// Обработчик события закрытия окна.
/// </summary>
/// <param name="parSender">Источник события.</param>
/// <param name="parE">Аргументы события закрытия окна.</param>
private void Window_Closing(object parSender, CancelEventArgs parE)
{
if (_isCompleted)
return;
if (!_isCancelled)
Cancel();
}
/// <summary>
/// Обработчик события нажатия на кнопку "Cancel/Close".
/// </summary>
/// <param name="parSender">Источник события.</param>
/// <param name="parE">Аргументы события.</param>
private void CancelButton_Click(object parSender, RoutedEventArgs parE)
{
if (!_isCompleted)
Cancel();
Close();
}
/// <summary>
/// Выполняет отмену задачи и отключает кнопку отмены.
/// </summary>
private void Cancel()
{
if (_isCancelled)
return;
_cancelButton.IsEnabled = false;
_isCancelled = true;
Cancelled?.Invoke(this, EventArgs.Empty);
}
}