【PowerShellでGUI 5】DataGridView

PowerShellで作成するWindwos Formアプリの部品のうち、今回はデータグリッドビューについてです。

DataGridView

今回のサンプルアプリの画面イメージはこちら。
少しは機能的なものにしてみようかと思い、今回は簡易なエクスプローラーライクなものにしてみました。

そして上記画面のソースコードがこちら

using namespace System.Windows.Forms
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing

[Application]::EnableVisualStyles()

# フォーム
$frame = New-Object Form -Property @{
    Text            = 'Sample App'
    Size            = New-Object Drawing.Size(650, 600)
    MaximizeBox     = $false
    FormBorderStyle = 'FixedDialog'
    Font            = New-Object Drawing.Font('Meiryo UI', 8.5)
}

# 表示対象フォルダー設定用テキストボックス
$tbxFolder = New-Object TextBox -Property @{
    Location      = New-Object Drawing.Point(20, 20)
    Width         = 400
    ReadOnly      = $True
}
$frame.Controls.Add($tbxFolder)

# フォルダー選択ダイアログ表示ボタン
$btnRef = New-Object Button -Property @{
    Location      = New-Object Drawing.Point(425, 20)
    Text          = '...'
    Width         = 30
}
$frame.Controls.Add($btnRef)

# 上位階層に移動するボタン
$btnUp = New-Object Button -Property @{
    Location      = New-Object Drawing.Point(460, 20)
    Text          = 'Up'
    Width         = 30
    Enabled       = $false
}
$frame.Controls.Add($btnUp)

$fbdRef = New-Object FolderBrowserDialog -Property @{
    ShowNewFolderButton = $false
}

# データグリッドビュー
$DataGridV = New-Object DataGridView -Property @{
    Location        = New-Object Drawing.Point(20, 50)
    Size            = New-Object Drawing.Size(600, 500)
    AutoSizeColumnsMode = "AllCells"
    ReadOnly            = $True
    AllowUserToAddRows  = $false
    ColumnCount         = 4
    RowHeadersVisible   = $false
    MultiSelect         = $false
    SelectionMode       = 'FullRowSelect'
}

# 各列の情報設定
$DataGridV.Columns[0].Name  = "名前"
$DataGridV.Columns[1].Name  = "更新日時"
$DataGridV.Columns[1].DefaultCellStyle.Format = 'yyyy/MM/dd HH:mm:ss'
$DataGridV.Columns[2].Name  = "IsContainer"
$DataGridV.Columns[2].Visible = $false
$DataGridV.Columns[3].Name  = "サイズ"
$DataGridV.Columns[3].DefaultCellStyle.Format = '#,##0 KB'
$DataGridV.Columns[3].DefaultCellStyle.Alignment = 'MiddleRight'

# DataGridViewに値を設定する処理
$scrbSetGrid = {
    $DataGridV.Rows.Clear()
    $files = (Get-ChildItem $tbxFolder.Text)
    foreach ($fi in $files){
        if (!$fi.PSIsContainer){
            switch ($fi.Length) {
                {$_ -lt 1024} { $size = 1  }
                Default {$size = ($_ / 1024)}
            }
        } else {
            $size = $null
        }
        $DataGridV.Rows.Add($fi.Name, $fi.LastWriteTime, $fi.PSIsContainer, $size)
    }
    $btnUp.Enabled = !([string]::IsNullOrEmpty((Split-Path $tbxFolder.Text -Parent)))
}

$btnRef.Add_Click({
    if ($fbdRef.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK){
        $tbxFolder.Text = $fbdRef.SelectedPath
        . $scrbSetGrid
    }
})

$btnUp.Add_Click({
    $tbxFolder.Text = (Split-Path $tbxFolder.Text -Parent)
    . $scrbSetGrid
})

# ダブルクリック時の処理
$DataGridV.Add_CellDoubleClick({
    if ($_.RowIndex -ge 0){
        if ($DataGridV.Rows[$_.RowIndex].Cells[2].Value -eq 'True'){
            $tbxFolder.Text = (Join-Path $tbxFolder.Text $DataGridV.Rows[$_.RowIndex].Cells[0].Value)
            . $scrbSetGrid
        } else {
            Start-Process -FilePath (Join-Path $tbxFolder.Text $DataGridV.Rows[$_.RowIndex].Cells[0].Value)
        }
    }
})

$frame.Controls.Add($DataGridV)

$frame.ShowDialog()

解説

46~56行目がデータグリッドビューの定義をしている部分になります。

$DataGridV = New-Object DataGridView -Property @{
    Location        = New-Object Drawing.Point(20, 50)
    Size            = New-Object Drawing.Size(600, 500)
    AutoSizeColumnsMode = "AllCells"
    ReadOnly            = $True
    AllowUserToAddRows  = $false
    ColumnCount         = 4
    RowHeadersVisible   = $false
    MultiSelect         = $false
    SelectionMode       = 'FullRowSelect'
}

データグリッドビューのプロパティは多数あるので、細かくはマイクロソフトの公式サイト
https://docs.microsoft.com/ja-jp/dotnet/api/system.windows.forms.datagridview?view=net-5.0
で確認してみるのがよいとは思いますが、今回設定しているものをいくつか説明すると、

AutoSizeColumnsMode列幅の自動調整モードの設定値で、今回設定している"AllCells"は、全ての行のデータを対象に、全体が表示される幅に調整するモードです。
AllowUserToAddRows新規の行の追加を許可するかどうかの設定値です。今回はそもそもReadOnlyに設定しているので、この設定がなくとも新規の行追加自体は行えないのですが、不許可の設定をしないと最下行に新規追加用の空行が表示されてしまうため、設定しています。
RowHeadersVisible左端のヘッダー列を表示/非表示の設定値で、今回は非表示にしています。
MultiSelect複数のセルや列、行の選択を許可するかどうかの設定で、今回は不許可に設定しています。
SelectionModeセルの選択のされ方の設定値で、今回は行全体が選択されるモードに設定しています。

59~66行目が、データグリッドビューの各列の属性を設定している部分で、
Nameプロパティでヘッダーに表示する文字列、
DefaultCellStyleでセルのデフォルトの書式設定を行っています。

$DataGridV.Columns[0].Name  = "名前"
$DataGridV.Columns[1].Name  = "更新日時"
$DataGridV.Columns[1].DefaultCellStyle.Format = 'yyyy/MM/dd HH:mm:ss'
$DataGridV.Columns[2].Name  = "IsContainer"
$DataGridV.Columns[2].Visible = $false
$DataGridV.Columns[3].Name  = "サイズ"
$DataGridV.Columns[3].DefaultCellStyle.Format = '#,##0 KB'
$DataGridV.Columns[3].DefaultCellStyle.Alignment = 'MiddleRight'

69~84行目はテキストボックスに設定されたフォルダの内容をデータグリッドビューに設定するスクリプトをスクリプトブロックとして定義したものです。
フォルダのダイアログでの選択後や、上位階層への移動ボタンのクリック等、数か所から実行されるので、スクリプトブロックにしてみました。

$scrbSetGrid = {
    $DataGridV.Rows.Clear()
    $files = (Get-ChildItem $tbxFolder.Text)
    foreach ($fi in $files){
        if (!$fi.PSIsContainer){
            switch ($fi.Length) {
                {$_ -lt 1024} { $size = 1  }
                Default {$size = ($_ / 1024)}
            }
        } else {
            $size = $null
        }
        $DataGridV.Rows.Add($fi.Name, $fi.LastWriteTime, $fi.PSIsContainer, $size)
    }
    $btnUp.Enabled = !([string]::IsNullOrEmpty((Split-Path $tbxFolder.Text -Parent)))
}

最後に、99~108行目は、データグリッドビュー内でダブルクリックをした際の処理になっています。
フォルダーの場合はそのフォルダに移動、その他の場合はWindowsの定義に従ってそのファイルが開かれるようになっています。

$DataGridV.Add_CellDoubleClick({
    if ($_.RowIndex -ge 0){
        if ($DataGridV.Rows[$_.RowIndex].Cells[2].Value -eq 'True'){
            $tbxFolder.Text = (Join-Path $tbxFolder.Text $DataGridV.Rows[$_.RowIndex].Cells[0].Value)
            . $scrbSetGrid
        } else {
            Start-Process -FilePath (Join-Path $tbxFolder.Text $DataGridV.Rows[$_.RowIndex].Cells[0].Value)
        }
    }
})

今回はここまで。
次回はデータグリッドビューの応用編として、データグリッドビュー内にチェックボックスやリンクを表示するパターンを記載予定です。

以上、参考になれば幸いです。