ProgressBar(プログレスバー)とは?
ProgressBarとは時間がかかる処理を非同期でさせている最中に,進捗状況を画面に表示するためのコントロールです。
主なプロパティ
- 進捗状況をValueに設定します。
- 最小値をMinimum,最大値をMaximumに設定します。パーセントで表示する場合は0から100で設定します。ファイル数等,処理の最大値がわかっている場合はその値を表示することで,どの程度作業が終わっているのかがユーザーに分かりやすくなります。
主なイベント
ValueChanged
Valueが変更されたときに通知されるので,このタイミングでTextBlockのTextプロパティに文字を設定することで,プログレスバーの目盛りだけではなく,文字でも表示することができるので,よりユーザーに分かりやすくなります。
表示形式
最初の画像で示している通り,主な表現の方法は3パターンあります。
パターン1:プログレスバーとテキストを別で表示する
この方法が一番簡単で一般的です。プログレスバーの周りにTextBlockなどを設置して,プログレスバーとテキスト表示を別で表示します。もちろんプログレスバー単体での表示も可能ですが,その場合,ユーザーは大体の値しか把握できなくなります。
<ProgressBar x:Name="AProgressBar"
Margin="25,0,0,0"
Height="30"
Width="180"
Minimum="0"
Maximum="100"
HorizontalAlignment="Left"
ValueChanged="AProgressBar_ValueChanged"
/>
<TextBlock x:Name="ATextBlock"
Margin="10,0,0,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Text="xxx"
Width="50"
FontSize="20"/>
<Button x:Name="AButton"
Margin="10,0,0,0"
Click="AButton_Click"
Height="30"
Width="60"
Content="Run"/>
</StackPanel>
public MainWindow()
{
InitializeComponent();
ATextBlock.Text = AProgressBar.Value.ToString() + "%";
}
private void AProgressBar_ValueChanged(object sender, RoutedPropertyChangedEventArgs e)
{
ATextBlock.Text = AProgressBar.Value.ToString() + "%";
}
private void AButton_Click(object sender, RoutedEventArgs e)
{
Task.Run(() =>
{
for (int i = 0; i < 10; i++)
{
System.Threading.Thread.Sleep(500);
Application.Current.Dispatcher.Invoke(() =>
{
AProgressBar.Value += 10;
});
}
});
}
- AButton_Clickの中では,時間のかかる処理を作るために, 500ミリ秒のSleepを10回実施しています。
- Sleep 1回実施されるたびにProgressBarのValueを10ずつ増やしています。
- 非同期処理の中でコントロールを操作できないため,Current.Dispatcher.Invokeで,UIスレッドに戻してから,プログレスバーの値を変更しています。
パターン2:プログレスバーとテキストを重ねて表示する
この表示の仕方も結構ニーズがあると思います。ProgressBar自体にこの方法を実現するプロパティは実装されていないので,自分で実装する必要があります。やり方はProgressBarとTextBlockを同一のGrid上に配置し,同一の列と行の設定にします。同一のGridにこの2つしかコントロールがない場合はどちらも行列がゼロになっているので,あえて行列の設定をする必要はありません。
<StackPanel Margin="5,10,5,5"
Orientation="Horizontal">
<Grid>
<ProgressBar x:Name="BProgressBar"
Margin="25,0,0,0"
Height="30"
Width="180"
Minimum="0"
Maximum="100"
HorizontalAlignment="Left"
ValueChanged="BProgressBar_ValueChanged"
/>
<TextBlock x:Name="BTextBlock"
Margin="10,0,0,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Text="xxx"
Width="50"
FontSize="20"/>
</Grid>
<Button x:Name="BButton"
Margin="10,0,0,0"
Click="BButton_Click"
Height="30"
Width="60"
Content="Run"/>
</StackPanel>
パターン1とほとんど同じです。違いはProgressBarとTextBlockを同一のGrid上に載せているだけです。
public MainWindow()
{
InitializeComponent();
BTextBlock.Text = BProgressBar.Value.ToString() + "%";
}
private void BProgressBar_ValueChanged(object sender, RoutedPropertyChangedEventArgs e)
{
BTextBlock.Text = BProgressBar.Value.ToString() + "%";
}
private void BButton_Click(object sender, RoutedEventArgs e)
{
Task.Run(() =>
{
for (int i = 0; i < 10; i++)
{
System.Threading.Thread.Sleep(500);
Application.Current.Dispatcher.Invoke(() =>
{
BProgressBar.Value += 10;
});
}
});
}
パターン3:終了するタイミングが不明な時
すべての処理が,終了するタイミングがわかるわけではありません。データベースの問い合わせなどは,データベースからの返答がいつになるかわかりません。そういった場合は,処理中であることだけを示し,画面が固まっていないことを表現するためにも,何かしらのアニメーションが動作しているほうが望ましいです。そういった場合にプログレスバーの目盛りが,左から右に永遠と流れるだけの機能が実装されています。やり方はIsIndeterminate
というプロパティをTrueにするだけです。処理が終わったらFalseにすれば止まります。パターン2のTextBlockを重ねる方法を利用して「検索しています…」等と表示すれば,一層の効果があります。
<StackPanel Margin="5,10,5,5"
Orientation="Horizontal">
<Grid>
<ProgressBar x:Name="CProgressBar"
Margin="25,0,0,0"
Height="30"
Width="180"
Minimum="0"
Maximum="100"
HorizontalAlignment="Left"
/>
<TextBlock x:Name="CTextBlock"
Margin="10,0,0,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Text=""
FontSize="14"/>
</Grid>
<Button x:Name="CButton"
Margin="10,0,0,0"
Click="CButton_Click"
Height="30"
Width="60"
Content="Run"/>
</StackPanel>
private void CButton_Click(object sender, RoutedEventArgs e)
{
CProgressBar.IsIndeterminate = true;
CTextBlock.Text = "検索しています...";
}
処理を実行したタイミングでIsIndeterminateをTrueにして,TextBlockに検索中の文言を表示しています。処理が終わったタイミングでIsIndeterminateをFalseにしたり,TextBlockの文言を消す必要があります。
サンプルコード全体
<Window x:Class="WPF019.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:WPF019"
mc:Ignorable="d"
Title="MainWindow" Height="170" Width="370">
<Grid>
<StackPanel>
<StackPanel Margin="5,10,5,5"
Orientation="Horizontal">
<ProgressBar x:Name="AProgressBar"
Margin="25,0,0,0"
Height="30"
Width="180"
Minimum="0"
Maximum="100"
HorizontalAlignment="Left"
ValueChanged="AProgressBar_ValueChanged"
/>
<TextBlock x:Name="ATextBlock"
Margin="10,0,0,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Text="xxx"
Width="50"
FontSize="20"/>
<Button x:Name="AButton"
Margin="10,0,0,0"
Click="AButton_Click"
Height="30"
Width="60"
Content="Run"/>
</StackPanel>
<StackPanel Margin="5,10,5,5"
Orientation="Horizontal">
<Grid>
<ProgressBar x:Name="BProgressBar"
Margin="25,0,0,0"
Height="30"
Width="180"
Minimum="0"
Maximum="100"
HorizontalAlignment="Left"
ValueChanged="BProgressBar_ValueChanged"
/>
<TextBlock x:Name="BTextBlock"
Margin="10,0,0,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Text="xxx"
Width="50"
FontSize="20"/>
</Grid>
<Button x:Name="BButton"
Margin="10,0,0,0"
Click="BButton_Click"
Height="30"
Width="60"
Content="Run"/>
</StackPanel>
<StackPanel Margin="5,10,5,5"
Orientation="Horizontal">
<Grid>
<ProgressBar x:Name="CProgressBar"
Margin="25,0,0,0"
Height="30"
Width="180"
Minimum="0"
Maximum="100"
HorizontalAlignment="Left"
/>
<TextBlock x:Name="CTextBlock"
Margin="10,0,0,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Text=""
FontSize="14"/>
</Grid>
<Button x:Name="CButton"
Margin="10,0,0,0"
Click="CButton_Click"
Height="30"
Width="60"
Content="Run"/>
</StackPanel>
</StackPanel>
</Grid>
</Window>
using System.Threading.Tasks;
using System.Windows;
namespace WPF019
{
///
/// MainWindow.xaml の相互作用ロジック
///
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
ATextBlock.Text = AProgressBar.Value.ToString() + "%";
BTextBlock.Text = BProgressBar.Value.ToString() + "%";
}
private void AProgressBar_ValueChanged(object sender, RoutedPropertyChangedEventArgs e)
{
ATextBlock.Text = AProgressBar.Value.ToString() + "%";
}
private void AButton_Click(object sender, RoutedEventArgs e)
{
Task.Run(() =>
{
for (int i = 0; i < 10; i++)
{
System.Threading.Thread.Sleep(500);
Application.Current.Dispatcher.Invoke(() =>
{
AProgressBar.Value += 10;
});
}
});
}
private void BProgressBar_ValueChanged(object sender, RoutedPropertyChangedEventArgs e)
{
BTextBlock.Text = BProgressBar.Value.ToString() + "%";
}
private void BButton_Click(object sender, RoutedEventArgs e)
{
Task.Run(() =>
{
for (int i = 0; i < 10; i++)
{
System.Threading.Thread.Sleep(500);
Application.Current.Dispatcher.Invoke(() =>
{
BProgressBar.Value += 10;
});
}
});
}
private void CButton_Click(object sender, RoutedEventArgs e)
{
CProgressBar.IsIndeterminate = true;
CTextBlock.Text = "検索しています...";
}
}
}
- C#WPFの道#1!WPFのプロジェクト作成方法をわかりやすく解説!
- C#WPFの道#2!StackPanelの使い方をわかりやすく解説!
- C#WPFの道#3!Gridの使い方をわかりやすく解説!
- C#WPFの道#4!コントロールの名前の付け方をわかりやすく解説!
- C#WPFの道#5!イベントの定義の仕方をわかりやすく解説!
- C#WPFの道#6!リソースとStaticResourceの定義と使い方をわかりやすく解説!
- C#WPFの道#7!コントロールのスタイル定義のやり方をわかりやすく解説!
- C#WPFの道#8!グループごとのスタイル定義とBasedOnでの継承のやり方!
- C#WPFの道#9!SQLiteの使い方をわかりやすく解説!
- C#WPFの道#10!ListViewの使い方をわかりやすく解説!
- C#WPFの道#11!ListViewのフィルタリングの方法を解説!
- C#WPFの道#12!SQLiteとListViewでマスタ設定画面の作成!
- C#WPFの道#13!Buttonに画像と文字を並べる方法とRepeatButtonとToggleButton
- C#WPFの道#14!CheckBoxとIsThreeState、Indeterminateの使い方
- C#WPFの道#15!RadioButtonの書き方と使い方を解説
- C#WPFの道#16!Expanderの書き方と使い方を解りやすく解説
- C#WPFの道#17!GroupBoxの書き方と使い方を解りやすく解説
- C#WPFの道#18!Slider(スライダー)の書き方と使い方を解りやすく解説
- C#WPFの道#19!ProgressBarの書き方と使い方を解りやすく解説
- C#WPFの道#20!ComboBoxの書き方と使い方を解りやすく解説
- C#WPFの道#21!ListBoxの書き方と使い方を解りやすく解説
- C#WPFの道#22!TabControlの書き方と使い方を解りやすく解説
- C#WPFの道#23!TreeViewの書き方と使い方を解りやすく解説
- C#WPFの道#24!TextBlock,TextBoxの改行と文字の加工を解説
- C#WPFの道#25!Menuの書き方と使い方をわかりやすく解説!
- C#WPFの道#26!ToolBarの書き方と使い方をわかりやすく解説!
- C#WPFの道#27!StatusBarの書き方と使い方をわかりやすく解説!
- C#WPFの道#28!WrapPanelの書き方と使い方をわかりやすく解説!
- C#WPFの道#29!DockPanelの書き方と使い方をわかりやすく解説!
- C#WPFの道#30!Canvasの書き方と使い方をわかりやすく解説!
