在 Powershell 表单中使用整数值对 Listview 控制列进行排序
Sorting Listview control columns with integer values in Powershell forms
我正在尝试对以下列表视图中的“大小 (kb)”列进行排序。 “大小 (kb)”列正在根据文本值进行排序,这不是预期的结果。我得到所有其他列的正确结果
# Defining the listbox fo displaying the search results
$lvw_resultsListView = New-Object System.Windows.Forms.ListView -Property @{
View = [System.Windows.Forms.View]::Details
Location = New-Object System.Drawing.Size(10, 40)
Width = 700
Height = 350
Scrollable = $true
MultiSelect = $true
Font = 'Arial,10'
AutoSize = $true
Sorting = "Ascending"
FullRowSelect = $true
GridLines = $True
}
这是将列添加到列表视图的代码
# Adding Columns to List View
$lvw_resultsListView.columns.Add("Filename", 150) | Out-Null
$lvw_resultsListView.columns.Add("Path", 340) | Out-Null
$lvw_resultsListView.columns.Add("Size (kb)", 90) | Out-Null
$lvw_resultsListView.columns.Add("Created on", 70) | Out-Null
$lvw_resultsListView.columns.Add("Ext", 60) | Out-Null
这是从文件对象添加值的代码
# Clearing list view items
$lvw_resultsListView.Items.Clear()
# Adding file information to the list bx by cycling through each file
foreach ($file in $global:files) {
$fileItem = New-Object System.Windows.Forms.ListViewItem( $file.BaseName)
$fileItem.Subitems.Add($file.FullName) | Out-Null
$fileItem.Subitems.Add($file.Length) | Out-Null
$tempCreationDate = $file.CreationTime | Get-Date -f "yyyy-MM-dd"
$fileItem.Subitems.Add($tempCreationDate) | Out-Null
$fileItem.Subitems.Add($file.Extension) | Out-Null
$lvw_resultsListView.Items.Add($fileItem) | Out-Null
}
这里是点击列时调用的排序函数
function SortListView {
Param(
[System.Windows.Forms.ListView] $senderPsItem,
$column
)
$temp = $senderPsItem.Items | Foreach-Object { $_ }
$Script:SortingDescending = !$Script:SortingDescending
$senderPsItem.Items.Clear()
$senderPsItem.ShowGroups = $false
$senderPsItem.Sorting = 'none'
if($column.Text -eq "Size (kb)") {
$senderPsItem.Items.AddRange(($temp | Sort-Object -Descending:$script:SortingDescending -Property @{ Expression={ [int]$_.SubItems[$column].Text } }))
} else {
$senderPsItem.Items.AddRange(($temp | Sort-Object -Descending:$script:SortingDescending -Property @{ Expression={ $_.SubItems[$column].Text } }))
}
}
这里(结果表单的片段)是我为“大小 (kb)”列获得的示例结果
这里是调用排序函数的代码
$lvw_resultsListView.Add_ColumnClick({SortListView $this $_.Column})
有人可以建议一种方法来改进我的排序功能以正确排序整数列。我尝试使用 [int] 方法将测试转换为整数,从排序函数中可以看出?
提前致谢!
用于检查“大小 (kb)”列的 IF 条件不正确。列索引用于解决此问题。
已更改
if($column.Text -eq "Size (kb)")
到
if($column -eq 2)
我更新了排序函数以更正 IF 条件
function SortListView {
Param(
[System.Windows.Forms.ListView] $senderPsItem,
$column
)
$temp = $senderPsItem.Items | Foreach-Object { $_ }
$Script:SortingDescending = !$Script:SortingDescending
$senderPsItem.Items.Clear()
$senderPsItem.ShowGroups = $false
$senderPsItem.Sorting = 'none'
Write-Host $column
if($column -eq 2) {
$senderPsItem.Items.AddRange(($temp | Sort-Object -Descending:$script:SortingDescending -Property @{ Expression={ [int]$_.SubItems[$column].Text } }))
} else {
$senderPsItem.Items.AddRange(($temp | Sort-Object -Descending:$script:SortingDescending -Property @{ Expression={ $_.SubItems[$column].Text } }))
}
}
这给出了整数列的正确结果。
在这里,试试这段代码,它会帮助你理解为什么我提到 DataGridView
和 DataTable
,这对我个人在使用 Windows 表单时产生了很大的影响。
尝试对 *Time
和 Length
列进行排序,您就会明白为什么了:)
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
Add-Type -AssemblyName PresentationFramework
$myFont='Helvetica'
$mainForm=New-Object System.Windows.Forms.Form
$mainForm.StartPosition='CenterScreen'
$mainForm.Icon=[System.Drawing.Icon]::ExtractAssociatedIcon("$PSHOME\PowerShell.exe")
$mainForm.KeyPreview=$True
$mainForm.FormBorderStyle='Fixed3D'
$mainForm.Text='Test'
$mainForm.WindowState='Maximized'
$bounds=($mainForm.CreateGraphics()).VisibleClipBounds.Size
$dataGrid=New-Object System.Windows.Forms.DataGridView
$dataGrid.Size=New-Object System.Drawing.Size(($bounds.Width-20),$($bounds.Height-140))
$dataGrid.Location=New-Object System.Drawing.Size(10,60)
$dataGrid.Font=New-Object System.Drawing.Font($myFont,9,[System.Drawing.FontStyle]::Regular)
$dataGrid.DefaultCellStyle.WrapMode='True'
$dataGrid.AllowUserToAddRows=$false
$dataGrid.SelectionMode=0
$dataGrid.MultiSelect=$True
$dataGrid.ReadOnly=$false
$dataGrid.EnableHeadersVisualStyles=$True
$datagrid.Anchor='Top, Bottom, Left'
$mainForm.Controls.Add($dataGrid)
#Here goes your Data Source
$dataSource = Get-ChildItem "$HOME\Documents" -File|select Name,Length,LastWriteTime,CreationTime
$columns=$dataSource[0].PSobject.Properties.Name
$table = New-Object system.Data.DataTable
foreach($column in $columns)
{
$type=switch -Wildcard($column)
{
'Length'{[int]}
'*Time'{[datetime]}
Default{[string]}
}
$i = New-Object System.Data.DataColumn
$i.DataType = $type
$i.ColumnName = $column
$table.Columns.Add($i)
}
foreach($line in $dataSource)
{
$row = $table.NewRow()
foreach($column in $columns)
{
$row.$column = $line.$column
}
$table.Rows.Add($row)
}
# Here you bind your DataSource to your DataGridView
$dataGrid.DataSource=$table
$dataGrid.RowHeadersVisible=$false
$dataGrid.ColumnHeadersBorderStyle=2
$dataGrid.AutoSizeColumnsMode=[System.Windows.Forms.DataGridViewAutoSizeColumnMode]::AllCells
$dataGrid.ColumnHeadersHeight=25
$sum=0
$dataGrid.Columns.Width|%{$sum+=$_}
if($sum -lt $dataGrid.Width)
{
$dataGrid.Columns[-1].AutoSizeMode=[System.Windows.Forms.DataGridViewAutoSizeColumnMode]::Fill
}
$mainForm.ShowDialog()
我正在尝试对以下列表视图中的“大小 (kb)”列进行排序。 “大小 (kb)”列正在根据文本值进行排序,这不是预期的结果。我得到所有其他列的正确结果
# Defining the listbox fo displaying the search results
$lvw_resultsListView = New-Object System.Windows.Forms.ListView -Property @{
View = [System.Windows.Forms.View]::Details
Location = New-Object System.Drawing.Size(10, 40)
Width = 700
Height = 350
Scrollable = $true
MultiSelect = $true
Font = 'Arial,10'
AutoSize = $true
Sorting = "Ascending"
FullRowSelect = $true
GridLines = $True
}
这是将列添加到列表视图的代码
# Adding Columns to List View
$lvw_resultsListView.columns.Add("Filename", 150) | Out-Null
$lvw_resultsListView.columns.Add("Path", 340) | Out-Null
$lvw_resultsListView.columns.Add("Size (kb)", 90) | Out-Null
$lvw_resultsListView.columns.Add("Created on", 70) | Out-Null
$lvw_resultsListView.columns.Add("Ext", 60) | Out-Null
这是从文件对象添加值的代码
# Clearing list view items
$lvw_resultsListView.Items.Clear()
# Adding file information to the list bx by cycling through each file
foreach ($file in $global:files) {
$fileItem = New-Object System.Windows.Forms.ListViewItem( $file.BaseName)
$fileItem.Subitems.Add($file.FullName) | Out-Null
$fileItem.Subitems.Add($file.Length) | Out-Null
$tempCreationDate = $file.CreationTime | Get-Date -f "yyyy-MM-dd"
$fileItem.Subitems.Add($tempCreationDate) | Out-Null
$fileItem.Subitems.Add($file.Extension) | Out-Null
$lvw_resultsListView.Items.Add($fileItem) | Out-Null
}
这里是点击列时调用的排序函数
function SortListView {
Param(
[System.Windows.Forms.ListView] $senderPsItem,
$column
)
$temp = $senderPsItem.Items | Foreach-Object { $_ }
$Script:SortingDescending = !$Script:SortingDescending
$senderPsItem.Items.Clear()
$senderPsItem.ShowGroups = $false
$senderPsItem.Sorting = 'none'
if($column.Text -eq "Size (kb)") {
$senderPsItem.Items.AddRange(($temp | Sort-Object -Descending:$script:SortingDescending -Property @{ Expression={ [int]$_.SubItems[$column].Text } }))
} else {
$senderPsItem.Items.AddRange(($temp | Sort-Object -Descending:$script:SortingDescending -Property @{ Expression={ $_.SubItems[$column].Text } }))
}
}
这里(结果表单的片段)是我为“大小 (kb)”列获得的示例结果
这里是调用排序函数的代码
$lvw_resultsListView.Add_ColumnClick({SortListView $this $_.Column})
有人可以建议一种方法来改进我的排序功能以正确排序整数列。我尝试使用 [int] 方法将测试转换为整数,从排序函数中可以看出? 提前致谢!
用于检查“大小 (kb)”列的 IF 条件不正确。列索引用于解决此问题。
已更改
if($column.Text -eq "Size (kb)")
到
if($column -eq 2)
我更新了排序函数以更正 IF 条件
function SortListView {
Param(
[System.Windows.Forms.ListView] $senderPsItem,
$column
)
$temp = $senderPsItem.Items | Foreach-Object { $_ }
$Script:SortingDescending = !$Script:SortingDescending
$senderPsItem.Items.Clear()
$senderPsItem.ShowGroups = $false
$senderPsItem.Sorting = 'none'
Write-Host $column
if($column -eq 2) {
$senderPsItem.Items.AddRange(($temp | Sort-Object -Descending:$script:SortingDescending -Property @{ Expression={ [int]$_.SubItems[$column].Text } }))
} else {
$senderPsItem.Items.AddRange(($temp | Sort-Object -Descending:$script:SortingDescending -Property @{ Expression={ $_.SubItems[$column].Text } }))
}
}
这给出了整数列的正确结果。
在这里,试试这段代码,它会帮助你理解为什么我提到 DataGridView
和 DataTable
,这对我个人在使用 Windows 表单时产生了很大的影响。
尝试对 *Time
和 Length
列进行排序,您就会明白为什么了:)
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
Add-Type -AssemblyName PresentationFramework
$myFont='Helvetica'
$mainForm=New-Object System.Windows.Forms.Form
$mainForm.StartPosition='CenterScreen'
$mainForm.Icon=[System.Drawing.Icon]::ExtractAssociatedIcon("$PSHOME\PowerShell.exe")
$mainForm.KeyPreview=$True
$mainForm.FormBorderStyle='Fixed3D'
$mainForm.Text='Test'
$mainForm.WindowState='Maximized'
$bounds=($mainForm.CreateGraphics()).VisibleClipBounds.Size
$dataGrid=New-Object System.Windows.Forms.DataGridView
$dataGrid.Size=New-Object System.Drawing.Size(($bounds.Width-20),$($bounds.Height-140))
$dataGrid.Location=New-Object System.Drawing.Size(10,60)
$dataGrid.Font=New-Object System.Drawing.Font($myFont,9,[System.Drawing.FontStyle]::Regular)
$dataGrid.DefaultCellStyle.WrapMode='True'
$dataGrid.AllowUserToAddRows=$false
$dataGrid.SelectionMode=0
$dataGrid.MultiSelect=$True
$dataGrid.ReadOnly=$false
$dataGrid.EnableHeadersVisualStyles=$True
$datagrid.Anchor='Top, Bottom, Left'
$mainForm.Controls.Add($dataGrid)
#Here goes your Data Source
$dataSource = Get-ChildItem "$HOME\Documents" -File|select Name,Length,LastWriteTime,CreationTime
$columns=$dataSource[0].PSobject.Properties.Name
$table = New-Object system.Data.DataTable
foreach($column in $columns)
{
$type=switch -Wildcard($column)
{
'Length'{[int]}
'*Time'{[datetime]}
Default{[string]}
}
$i = New-Object System.Data.DataColumn
$i.DataType = $type
$i.ColumnName = $column
$table.Columns.Add($i)
}
foreach($line in $dataSource)
{
$row = $table.NewRow()
foreach($column in $columns)
{
$row.$column = $line.$column
}
$table.Rows.Add($row)
}
# Here you bind your DataSource to your DataGridView
$dataGrid.DataSource=$table
$dataGrid.RowHeadersVisible=$false
$dataGrid.ColumnHeadersBorderStyle=2
$dataGrid.AutoSizeColumnsMode=[System.Windows.Forms.DataGridViewAutoSizeColumnMode]::AllCells
$dataGrid.ColumnHeadersHeight=25
$sum=0
$dataGrid.Columns.Width|%{$sum+=$_}
if($sum -lt $dataGrid.Width)
{
$dataGrid.Columns[-1].AutoSizeMode=[System.Windows.Forms.DataGridViewAutoSizeColumnMode]::Fill
}
$mainForm.ShowDialog()