Search code examples
formspowershelllistviewtype-conversioncolumnsorting

Sorting Listview control columns with integer values in Powershell forms


I am trying to sort the column "Size (kb)" in the following Listview. The "Size (kb)" column is getting sorted on basis of the text value which is not the intended result. I am getting correct results for all other columns

# 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
}

Here is the code that adds columns to the Listview

# 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

Here is the code that adds values from a file object

# 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
}

And here is the sorting function that is called on column click

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 } }))

    }
}

Here(snippet from the results form) is a sample result I am getting for the "Size (kb)" column

enter image description here

Here is the code calling sorting function

$lvw_resultsListView.Add_ColumnClick({SortListView $this $_.Column})

Could someone suggest a way to improve my sort function to properly sort the integer column. I tried converting the test to integer by using [int] method as may be seen from the sorting function? Thank you in advance!


Solution

  • The IF condition for checking the column "Size (kb)" was not correct. The column index was used to fix this.

    Changed

    if($column.Text -eq "Size (kb)")

    to

    if($column -eq 2)

    I updated the sorting unction to correct the IF condition

    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 } }))
    
        }
    }
    

    This gives the correct results for the integer column.