arrays - 如何将 2 个不同的数组放在列表视图的不同列中
问题描述
我正在尝试创建一个包含 2 个单独列的列表视图。第一列应显示文件夹名称列表。第二列应显示文件夹中特定文件的最后修改日期。
数组 1 = 文件夹列表
数组 2 = 文件夹列表中文件的修改日期
我能够创建数组并列出文件夹名称,但是在使用文件夹中文件的修改日期填充第二列时遇到问题。“echo $filedate.lastwritetime”正确显示了所有最后修改的日期,但是当我尝试在 ListView 列中显示它时,所有行只显示 1 个日期。
$path = C:\Test\
$folders = Get-ChildItem $path
foreach ($folder in $folders) {
$filedate = Get-ChildItem -Path $path\$folder\"Last Backed Up.txt"
echo $filedate.LastWriteTime
}
[void]$listView.Columns.Add("Folder Name", 150);
[void]$listView.Columns.Add("Last Modified Date", 150);
$folders | ForEach-Object {
$row = New-Object System.Windows.Forms.ListViewItem($_.Name)
[void]$row.SubItems.Add($filedate.LastWriteTime.Tostring())
[void]$listView.Items.Add($row)
}
$form.Controls.Add($listview)
$form.Topmost = $true
$result = $form.ShowDialog()
解决方案
不需要有两个数组并遍历$folders
数组两次。这可以在一个循环中完成。
由于不确定所有文件夹实际上都包含一个名为 的文件Last Backed Up.txt
,因此我建议您执行以下操作。对您来说有趣的部分是$folders | ForEach-Object {..}
循环,因为您已经准备好表单。为了清楚起见,代码完整:
$path = 'C:\Test'
# get an array of subfolder objects in the root folder $path
$folders = Get-ChildItem -Path $path -Directory # should we add -Recurse to also dig into any subfolder?
# build your form
Add-Type -AssemblyName System.Windows.Forms
$form = New-Object System.Windows.Forms.Form
$form.Text = "Backup Folders"
$form.Size = New-Object System.Drawing.Size(600,400)
$form.StartPosition = "CenterScreen"
$form.TopMost = $true
$listView = New-Object System.Windows.Forms.ListView
$listView.Location = New-Object System.Drawing.Point(10,40)
$listView.Size = New-Object System.Drawing.Size(560,280)
$listView.Anchor = 'Top,Right,Bottom,Left'
$listView.View = 'Details'
$listView.FullRowSelect = $true
$listView.GridLines = $true
# add two columns to the listView
[void]$listView.Columns.Add("Folder Name", 150)
[void]$listView.Columns.Add("Last Modified Date", 150)
# iterate through the list of folders
$folders | ForEach-Object {
# try to get the LastWriteTime of the file 'Last Backed Up.txt' inside this folder
$file = Get-Item -Path (Join-Path -Path $_.FullName -ChildPath 'Last Backed Up.txt') -ErrorAction SilentlyContinue
if ($file) { $date = $file.LastWriteTime.Tostring() } else { $date = '' }
# create a new row for the listview
$row = New-Object System.Windows.Forms.ListViewItem( $_.Name ) # first colum: the folder name
[void]$row.SubItems.Add($date) # second colum: the file LastWriteTime
[void]$listView.Items.Add($row)
}
$form.Controls.Add($listview)
# add an event handler on the listbox to do something with the selected item
$listView.Add_Click({
# here put your code to perform some action with the selected subfolder
$selected = $listView.SelectedItems[0].Text
$lastModified = $listView.SelectedItems[0].SubItems[1].Text
# for demo, simply show a messagebox
if ([string]::IsNullOrWhiteSpace($lastModified)) {
$message = "Subfolder '$selected' was never backed up"
}
else {
$message = "Subfolder '$selected' was last backed up on $lastModified"
}
[System.Windows.Forms.MessageBox]::Show($message, "Backup")
})
[void]$form.ShowDialog()
# we're done, so remove the form from memory
$form.Dispose()
PS 在您的代码中,所有行仅显示一个日期这一事实是因为您$filedate
在第一个循环的每次迭代中都重置了变量。因此,只有最后一个文件被捕获在变量中。
更新
因为您希望能够像您评论的那样对列表视图中的项目进行排序,所以我将代码更新如下。
它现在响应单击列标题以动态排序。
最初,列表视图显示在“文件夹名称”列上按升序排序的项目。
如果您单击“上次修改日期”列标题,它将按显示的日期对项目进行排序。再次单击同一列标题会将排序从升序切换到降序,反之亦然。
$path = 'C:\Test'
# get an array of subfolder objects in the root folder $path
$folders = Get-ChildItem -Path $path -Directory # should we add -Recurse to also dig into any subfolder?
# build your form
Add-Type -AssemblyName System.Windows.Forms
$form = New-Object System.Windows.Forms.Form
$form.Text = "Backup Folders"
$form.Size = New-Object System.Drawing.Size(600,400)
$form.StartPosition = "CenterScreen"
$form.TopMost = $true
$listView = New-Object System.Windows.Forms.ListView
$listView.Location = New-Object System.Drawing.Point(10,40)
$listView.Size = New-Object System.Drawing.Size(560,280)
$listView.Anchor = 'Top,Right,Bottom,Left'
$listView.View = 'Details'
$listView.FullRowSelect = $true
$listView.GridLines = $true
$listView.Sorting = [System.Windows.Forms.SortOrder]::None # IMPORTANT
# add two columns to the listView
[void]$listView.Columns.Add("Folder Name", 150)
[void]$listView.Columns.Add("Last Modified Date", 150)
# iterate through the list of folders initially sort the items by FolderName (column 1) ascending
# $items will be an array of objects to help sorting whatever is displayed in the listview
$items = $folders | ForEach-Object {
# try to get the LastWriteTime of the file 'Last Backed Up.txt' inside this folder
$file = Get-Item -Path (Join-Path -Path $_.FullName -ChildPath 'Last Backed Up.txt') -ErrorAction SilentlyContinue
# emit an object to be collected in the $items array
[PsCustomObject]@{
'FolderName' = $_.Name
'Modified' = if ($file) { $file.LastWriteTime } # a real DateTime object here for accurate sorting
}
} | Sort-Object FolderName
# create three script-scoped variables to keep score of the current sort
$script:sortColumn = 0
$script:sortDescending = $false
$script:sortProperty = @('FolderName', 'Modified')[$script:sortColumn]
# fill the listview for the first time
$items | ForEach-Object {
# create a new row for the listview
$row = New-Object System.Windows.Forms.ListViewItem( $_.FolderName ) # first colum: the folder name
if ($_.Modified) { [void]$row.SubItems.Add($_.Modified.ToString()) } # second colum: the file LastWriteTime
[void]$listView.Items.Add($row)
}
# add an event handler for when the user clicks on one of the column headers
$listView.Add_ColumnClick({
param($sender, $e) # $sender is the listview itself, $e is ColumnClickEventArgs
if ($e.Column -eq $script:sortColumn) {
# click on the currently sorted column --> reverse sort
$script:sortDescending = $script:sortDescending -xor $true
}
else {
$script:sortColumn = $e.Column
$script:sortDescending = $false
$script:sortProperty = @('FolderName', 'Modified')[$script:sortColumn]
}
# now sort the $items array on property $script:sortProperty in the
$temp = $items | Sort-Object $script:sortProperty -Descending:$script:sortDescending
# redraw the listview items
# using SuspendLayout() method before and ResumeLayout() after adding the items increases the performance
$listView.SuspendLayout()
$listView.Items.Clear()
$temp | ForEach-Object {
# create a new row for the listview
$row = New-Object System.Windows.Forms.ListViewItem( $_.FolderName ) # first colum: the folder name
if ($_.Modified) { [void]$row.SubItems.Add($_.Modified.ToString()) } # second colum: the file LastWriteTime
[void]$listView.Items.Add($row)
}
$listView.ResumeLayout()
$temp = $null
})
# add an event handler on the listbox to do something with the selected item
$listView.Add_Click({
# here put your code to perform some action with the selected subfolder
$selected = $listView.SelectedItems[0].Text
$lastModified = $listView.SelectedItems[0].SubItems[1].Text
# for demo, simply show a messagebox
if ([string]::IsNullOrWhiteSpace($lastModified)) {
$message = "Subfolder '$selected' was never backed up"
}
else {
$message = "Subfolder '$selected' was last backed up on $lastModified"
}
[System.Windows.Forms.MessageBox]::Show($message, "Backup")
})
$form.Controls.Add($listview)
[void]$form.ShowDialog()
# we're done, so remove the form from memory
$form.Dispose()
推荐阅读
- unity3d - Physics2D.OverLapBox 检测应忽略的对象
- regex - 如何使用 Spark 在 Scala 中为 Regex 类构建编码器
- r - R中的内存分析:如何找到最大内存使用的位置?
- python - 在不知道聚类数量的情况下根据起点和终点对线进行聚类
- java - Spring Boot项目上的Hibernate SessionFactory注入不起作用
- c# - 如何将 Double 存储在 Type 变量中?
- python - Numpy,将数据帧乘以输出 NaN 的数字
- recommendation-engine - 在 CF item-item 推荐器中,当矩阵稀疏时如何计算项目相似度?
- java - 如何使用最终 int 设置字符串数组的大小?
- java - Map 中的 Java 流