Всем привет. В данной статье мы с вами разберём, как работать с элементом ProgressBar в C# и напишем тестовое приложение, демонстрирующее его работу.
В статье не будет рассказано про запуск какого-либо процесса и отражение хода его выполнения с помощью элемента ProgressBar, равно как и не рассматривается взаимодействие ProgressBar с элементом BackgroundWorker. Для этой цели есть отдельная статья: Пишем на C# программу для поиска файлов, используя ProgressBar и BackgroundWorker. В рамках текущей статьи рассматриваются совсем базовые свойства элемента ProgressBar и синтетический пример заполнения его индикатора вручную.
Элемент ProgressBar доступен среди набора стандартных элементов, предоставляемых в Windows Forms. Как следует из названия этого элемента, он используется для индикации состояния прогресса выполнения какого-то процесса. Например, это может быть копирование файлов, установка программы, выполнение какой-то фоновой задачи и так далее - здесь всё зависит от решаемой задачи, для которой необходимо использовать ProgressBar.
В проекте для Windows Forms элемент будет доступен на панели элементов, он выглядит так:
Мы напишем простое приложение для Windows Forms в среде разработки Microsoft Visual Studio, которое покажет основные возможности элемента ProgressBar. При старте нашего приложения будет происходить заполнение прогресса для какого-то абстрактного тестового процесса/задачи. Можно будет остановить процесс и вместе с ним заполнение прогресс бара, а также можно будет сбросить весь процесс и начать его сначала. Мы также будем выводить процент выполнения процесса и отображать некий текстовый статус в отдельных метках, чтобы пользователь программы понимал, что происходит с программой. Наконец, в поле "Шаг прогресс бара" мы сможем поменять шаг заполнения прогресс бара (шаг влияет на скорость продвижения индикатора прогресса). Выглядеть приложение будет следующим образом:
Начнём с создания нового проекта в среде разработки Microsoft Visual Studio. При прохождении шагов в мастере создания нового проекта выберем тип проекта "Приложение Windows Forms (.NET Framework)", а в качестве имени проекта выберем ProgressBarSample. Когда проект будет создан, выберем главную форму и в окне "Свойства" изменим её название со стандартного Form1 на FrmProgressBarSample:
Также поменяем название файла формы в окне "Обозреватель решений" - с предлагаемого по умолчанию имени Form1.cs мы переименуем класс в FrmProgressBarSample.cs. Для этого выберем файл класса главной формы и нажмём F2 (либо в контекстном меню выберем пункт меню "Переименовать"), затем введём новое название класса FrmProgressBarSample.cs. В итоге у нас должно получиться следующее:
Выделим главную форму в режиме конструктора и зададим ей следующие свойства:
- StartPosition - CenterScreen
- Size - 658; 180
- FormBorderStyle - FixedSingle
- Text - [Allineed.Ru] Пример работы с элементом ProgressBar
- MaximizeBox - False
- MinimizeBox - False
Теперь настало время разместить на главной форме приложения необходимые элементы управления, включая и сам ProgressBar.
Перетаскиваем на главную форму следующие элементы из панели элементов:
- 1 элемент ProgressBar
- 5 элементов Label
- 2 элемента Button
- 1 элемент ComboBox
- 1 элемент Timer
Далее по очереди выберем каждый элемент, размещённый на форме и установим им следующие свойства:
элемент ProgressBar:
- Name - ProgressBarProcess
- Size - 616; 23
- Location - 12; 21
1-я метка (с текстом "Выполнено"):
- Name - LabelPercentComplete
- Location - 9; 47
- Text - Выполнено:
2-я метка (для отображения процента заполнения прогресс бара):
- Name - LabelPercentCompleteText
- Location - 82; 47
- Text - %
- Font - Microsoft Sans Serif; 8,25pt; style=Bold
3-я метка (с текстом "Статус"):
- Name - LabelStatus
- Location - 9; 69
- Text - Статус:
4-я метка (для отображения статуса выполнения задачи):
- Name - LabelStatusText
- Location - 82; 69
- Text - ?
- Font - Microsoft Sans Serif; 8,25pt; style=Bold
5-я метка (с текстом "Шаг прогресс бара"):
- Name - LabelProgressStep
- Location - 328; 111
- Text - Шаг прогресс бара:
1-я кнопка (с текстом "Сброс"):
- Name - ButtonReset
- Location - 13; 106
- Size - 130; 23
- Text - &Сброс
2-я кнопка (с текстом "Остановить"):
- Name - ButtonStop
- Location - 149; 106
- Size - 130; 23
- Text - &Остановить
элемент ComboBox:
- Name - ComboBoxProgressStep
- Location - 441; 108
- Size - 121; 21
- DropDownStyle - DropDownList
элемент Timer:
- Name - TimerForProgressBar
- Enabled - True
- Interval - 1000
Окно конструктора формы с расположенными на ней элементами теперь должно выглядеть следующим образом:
Теперь перейдем к программированию элементов формы.
Дважды кликнем на форме, в результате чего мы перейдем к коду формы, и для нас будет сгенерирован метод с именем FrmProgressBarSample_Load для обработки события загрузки формы.
При загрузке формы мы хотим инициализировать наш выпадающий список "Шаг прогресс бара" какими-то предопределёнными значениями. Давайте создадим небольшой внутренний класс с именем ProgressStep, который будет отвечать за хранение пары значений - процент продвижения прогресс бара и соответствующее ему целочисленной значение. Добавим следующее объявление класса ProgressStep внутри класса формы FrmProgressBarSample:
public partial class FrmProgressBarSample : Form {
class ProgressStep {
public string StepText { get; set; }
public int StepValue { get; set; }
public ProgressStep(string stepText, int stepValue) {
StepText = stepText;
StepValue = stepValue;
}
public override string ToString() {
return StepText;
}
}
private void FrmProgressBarSample_Load(object sender, EventArgs e) {
}
}
Как видим, внутри класса ProgressStep у нас есть два поля StepText (тип string) и StepValue (тип int). Также мы добавили в класс конструктор с параметрами, с помощью которого мы сможем быстро создавать объекты класса, передавая нужные нам значения. Заметим и то, что с помощью ключевого слова override мы переопределяем метод ToString() в классе, возвращая значение поля StepText - это нам необходимо для того, чтобы любые объекты класса ProgressStep, помещённые в элемент ComboBox на форме с именем ComboBoxProgressStep автоматически "умели" себя привести к строковому значению и вывести в выпадающем списка строковые значения вида "10%", "20%" и так далее.
Теперь где-нибудь ниже сгенерированного метода FrmProgressBarSample_Load напишем новый метод, который добавит 5 предопределённых значений процента в ComboBox. Назовём новый метод FillProgressSteps():
private void FillProgressSteps() {
ComboBoxProgressStep.Items.Add(new ProgressStep("10%", 10));
ComboBoxProgressStep.Items.Add(new ProgressStep("20%", 20));
ComboBoxProgressStep.Items.Add(new ProgressStep("30%", 30));
ComboBoxProgressStep.Items.Add(new ProgressStep("40%", 40));
ComboBoxProgressStep.Items.Add(new ProgressStep("50%", 50));
}
Этот метод по сути инициализирует доступные значения шага для нашего прогресс бара, которые легко можем поменять на форме.
Далее мы создадим ещё один метод UpdateProgressBarPercentComplete(), который будет обновлять текст в метке с именем LabelPercentCompleteText и будет выводить текущее значение процента выполнения. Значение текущего процента выполнения есть у нашего прогресс бара ProgressBarProcess, и оно хранится в специальном свойстве Value. Метод также будет проверять значение прогресса на попадание в определённые диапазоны значений и, в зависимости от этих диапазонов, будет менять текст в метке LabelStatusText, отражая статус текущего шага:
private void UpdateProgressBarPercentComplete() {
LabelPercentCompleteText.Text = ProgressBarProcess.Value + "%";
if (ProgressBarProcess.Value >= 0 && ProgressBarProcess.Value < 20) {
LabelStatusText.Text = "Инициализация...";
} else if (ProgressBarProcess.Value >= 20 && ProgressBarProcess.Value < 40) {
LabelStatusText.Text = "Подготовка примера...";
} else if (ProgressBarProcess.Value >= 40 && ProgressBarProcess.Value < 60) {
LabelStatusText.Text = "Выполнение задачи #1...";
} else if (ProgressBarProcess.Value >= 60 && ProgressBarProcess.Value < 80) {
LabelStatusText.Text = "Выполнение задачи #2...";
} else if (ProgressBarProcess.Value >= 80 && ProgressBarProcess.Value < 100) {
LabelStatusText.Text = "Почти готово, завершение...";
} else {
LabelStatusText.Text = "Выполнено.";
}
}
Теперь, когда методы готовы, мы вызовем их при загрузке нашей главной формы. Для этого просто добавим 2 строки кода в обработчик загрузки формы:
private void FrmProgressBarSample_Load(object sender, EventArgs e) {
UpdateProgressBarPercentComplete();
FillProgressSteps();
}
На этом этапе можем запустить форму и посмотреть на результат: мы увидим, что в выпадающем списке "Шаг прогресс бара" теперь доступны значения 10%, 20%, 30%, 40% и 50%, а напротив метки "Выполнено" увидим значение текущего прогресса - 0%.
Сделаем так, чтобы по при вызове события Tick таймера каждый раз выполнялся 1 шаг нашего прогресс бара. Для этого находим в конструкторе формы таймер TimerForProgressBar и дважды кликнем по нему. В результате в коде формы будет сгенерирован метод-обработчик TimerForProgressBar_Tick для таймера. Напишем в нём такой код:
private void TimerForProgressBar_Tick(object sender, EventArgs e) {
ProgressBarProcess.PerformStep();
UpdateProgressBarPercentComplete();
ButtonStop.Enabled = ProgressBarProcess.Value != 100;
if (ProgressBarProcess.Value >= 100) {
TimerForProgressBar.Stop();
}
}
С помощью вызова метода PerformStep() у прогресс бара выполняется увеличение на величину Step внутреннего значения прогресс бара, которое хранится в поле Value, а также производится отрисовка текущего прогресса.
Затем мы вызываем уже известный нам метод UpdateProgressBarPercentComplete(), который обновит процент выполненного прогресса и статус задачи.
Мы также регулируем доступность кнопки "&Остановить" - она доступна только тогда, когда значение прогресс бара не равно 100.
В последнем условии метода мы также проверяем поле ProgressBarProcess.Value - если оно больше или равно 100, то мы останавливаем сам таймер.
Теперь напишем код для наших кнопок "&Сброс" и "&Остановить". Дважды кликнем по каждой кнопке в конструкторе формы - будет сгенерированы методы ButtonStop_Click и ButtonReset_Click, которые наполним следующим кодом:
private void ButtonStop_Click(object sender, EventArgs e) {
if (TimerForProgressBar.Enabled) {
TimerForProgressBar.Stop();
ButtonStop.Text = "&Продолжить";
} else {
TimerForProgressBar.Start();
ButtonStop.Text = "&Остановить";
}
}
private void ButtonReset_Click(object sender, EventArgs e) {
ProgressBarProcess.Value = 0;
UpdateProgressBarPercentComplete();
if (!TimerForProgressBar.Enabled) {
TimerForProgressBar.Start();
}
}
Кнопка "&Остановить" и её метод-обработчик ButtonStop_Click проверяет текущее состояние таймера - если он включен, то таймер останавливаем и переименовываем название кнопки на "&Продолжить". И наоборот - если таймер выключен - запускаем его и переименовываем кнопку обратно в "&Остановить".
Кнопка "&Сброс" и её метод-обработчик ButtonReset_Click устанавливает значение прогресс бара в значение 0, а затем вызывает перерисовку процента выполнения и названия текущего шага - при помощи вызова метода UpdateProgressBarPercentComplete(). Также происходит проверка, что если таймер сейчас не включен, то мы его включаем для начала выполнения процесса.
Нам осталось последнее - при изменении индекса выбранного элемента в выпадающем ComboBox - получить выбранный элемент (это будет экземпляр нашего класса ProgressStep) и установить шаг для прогресс бара выбранным значением. Для этого на форме выберем ComboBox и дважды кликнем на нём. Сгенерируется метод-обработчик для события SelectedIndexChanged (оно происходит при смене индекса выбранного элемента), заполним его таким кодом:
private void ComboBoxProgressStep_SelectedIndexChanged(object sender, EventArgs e) {
if (ComboBoxProgressStep.SelectedItem != null) {
ProgressStep step = (ProgressStep)ComboBoxProgressStep.SelectedItem;
ProgressBarProcess.Step = step.StepValue;
}
}
На этом код нашего примера полностью готов. Запустим приложение и видим, как прогресс бар начинает постепенно заполняться, а напротив поля "Статус" изменяется текст с описанием выполняемого шага. Попробуем поиграть с формой - понажимаем кнопки "&Остановить" и "&Сброс" и посмотрим, как ведёт себя прогресс бар. Можем также изменять значение шага прогресса, чтобы ускорить/замедлить заполнение прогресс бара.
Проект с готовыми исходными кодами примера вы можете скачать в нашем каталоге по этой ссылке.