今回は検索なんかをやる予定でしたが、ちょっと寄り道して
選択されたファイル、フォルダの総数とデータ容量を非同期で画面に表示してみました。
プログラムは前回のものを流用します。
【C#】TreeView と ListView でエクスプローラーみたいな操作をする
リストビューの下にラベルを設置します。
// 非同期処理のキャンセル用変数
private CancellationTokenSource tokenSource = null;
/// <summary>
/// ファイル数とファイルサイズを設定します.
/// </summary>
private void SetFileCountAndSize()
{
// ファイル数、サイズの設定
try
{
// 非同期処理中だった場合はキャンセル
if (tokenSource != null)
{
tokenSource.Cancel();
}
using (tokenSource = new CancellationTokenSource())
{
SetFileCountAndSizeAsync(tokenSource.Token);
}
}
catch (ObjectDisposedException oe)
{
Console.WriteLine("非同期処理が中止されました。");
}
catch (OperationCanceledException ex)
{
MessageBox.Show("ファイル情報の取得に失敗しました。", "エラー");
return;
}
finally
{
tokenSource = null;
}
}
/// <summary>
/// ファイル数とファイルサイズを設定します(非同期処理).
/// </summary>
private async void SetFileCountAndSizeAsync(CancellationToken token)
{
long fileSize = 0;
int fileCount = 0;
lbl_fileCountValue.Text = "";
lbl_fileSizeValue.Text = "";
foreach (ListViewItem item in listViewTo.Items)
{
token.ThrowIfCancellationRequested();
// ディレクトリだった場合
FileInfo fi = new FileInfo(item.Name);
if (fi.Attributes == FileAttributes.Directory)
{
string[] pathList = Directory.GetDirectories(item.Name, "*", SearchOption.AllDirectories);
foreach (string path in pathList)
{
List<long> data = await GetFileCountAndSizeTask(path, fileSize, fileCount);
lbl_fileSizeValue.Text = getFileSize(data[0]);
lbl_fileCountValue.Text = data[1].ToString();
fileSize = data[0];
fileCount = (int)data[1];
}
}
else
{
fileSize += fi.Length;
fileCount++;
lbl_fileSizeValue.Text = getFileSize(fileSize);
lbl_fileCountValue.Text = fileCount.ToString();
}
}
}
/// <summary>
/// ファイル数とファイルサイズを取得します.
/// </summary>
/// <param name="filePath"></param>
/// <param name="fileSize"></param>
/// <param name="fileCount"></param>
/// <returns></returns>
private async Task<List<long>> GetFileCountAndSizeTask(String filePath, long fileSize, int fileCount)
{
List<long> result = new List<long>();
await Task.Run(() =>
{
DirectoryInfo dirInfo = new DirectoryInfo(filePath);
// フォルダ内の全ファイルの合計サイズを計算する
foreach (FileInfo fi in dirInfo.GetFiles())
{
fileSize += fi.Length;
fileCount++;
}
result.Add(fileSize);
result.Add(fileCount);
});
return result;
}
ファイルの追加、削除時にファイルサイズを設定する。
/// <summary>
/// 追加ボタンクリックイベント.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btn_add_Click(object sender, EventArgs e)
{
var selectedItems = listView1.SelectedItems;
foreach (ListViewItem item in selectedItems)
{
// 項目をコピーして名前を再設定
ListViewItem copy = (ListViewItem)item.Clone();
copy.Name = item.Name;
// 既にリストに含まれていないパスであれば追加
if (listViewTo.Items.Find(copy.Name, false).Length == 0)
{
listViewTo.Items.Add(copy);
}
}
// ファイル数、サイズの設定
SetFileCountAndSize();
// 列幅を自動調整
listViewTo.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);
}
/// <summary>
/// 削除ボタンクリックイベント.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btn_del_Click(object sender, EventArgs e)
{
var selectedItems = listViewTo.SelectedItems;
foreach (ListViewItem item in selectedItems)
{
listViewTo.Items.Remove(item);
}
// ファイル数、サイズの設定
SetFileCountAndSize();
// 列幅を自動調整
listViewTo.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);
}
スクリーンショットだと分からないですが、ファイル数、データ容量の大きいフォルダなんかを選択した場合に、非同期で表示が更新されます。
最初は非同期でない方法で試したのですが、
大きいファイルなんかだと画面が固まってしまうので非同期にしました。
やっぱり画面まわりも色々やれることがあって楽しいですね。
次回はボタンに画像を表示してみたいと思います。
Crieitは誰でも投稿できるサービスです。 是非記事の投稿をお願いします。どんな軽い内容でも投稿できます。
また、「こんな記事が読みたいけど見つからない!」という方は是非記事投稿リクエストボードへ!
こじんまりと作業ログやメモ、進捗を書き残しておきたい方はボード機能をご利用ください。
ボードとは?
コメント