Search code examples
powershellformslistboxtooltip

Tooltip text not updating in listbox when I move up the list


I have a powershell script where I look for and sort some files to populate a multiselect listbox. I added a function and a handler to show a tooltip with the "last modified" date whenever I click an element from the list. However, after selecting an item, the tooltip text value will not update if I select a different item in a position above that one, showing that one's last modified date instead. Can someone please help me understad why this is happening? I thought it had to do with the sorting, but the result is the same without sorting it. My code should always take the last one selected, no?

#MAIN WINDOW
$form = New-Object System.Windows.Forms.Form
$form.Size = New-Object System.Drawing.Size(620,400)
$form.StartPosition = "CenterScreen"
$form.FormBorderStyle = "Sizable"

#SOURCE FILES FOLDER
$sourceFolder = "C:\Users\me\Downloads"

#FILE LISTBOX
$sourceListBox = New-Object System.Windows.Forms.ListBox
$sourceListBox.SelectionMode = "MultiSimple"
$sourceListBox.Size = New-Object System.Drawing.Size(250,310)
$sourceListBox.Location = New-Object System.Drawing.Point(20,30)

#SEARCH FOR FILES
$sourceFiles = Get-ChildItem -Path $sourceFolder -Filter "*.pdf" | Sort-Object LastWriteTime -Descending | Select-Object -ExpandProperty Name
$sourceListBox.Items.AddRange($sourceFiles)
$form.Controls.Add($sourceListBox)

#TOOLTIP
$toolTip = New-Object System.Windows.Forms.ToolTip

#UPDATE TOOLTIP FROM LAST SELECTED ITEM
function ShowLastModifiedDateTooltip {
    $selectedItems = $sourceListBox.SelectedItems
    if ($selectedItems.Count -gt 0) {
        $lastSelectedItem = $selectedItems[$selectedItems.Count - 1]
        $sourcePath = Join-Path $sourceFolder $lastSelectedItem
        $lastModifiedDate = (Get-Item $sourcePath).LastWriteTime.ToString("dd-MM-yyyy")
        $toolTip.SetToolTip($sourceListBox, "Modified: $lastModifiedDate")
    }
}

#HANDLE CLICKS IN THE LISTBOX
$sourceListBox.Add_Click({
    ShowLastModifiedDateTooltip
})
$form.ShowDialog()

Solution

  • You can use the logic from this answer to always get the index of the lastly selected item from your ListBox. In addition, you should use the SelectedIndexChanged event instead of the Click event.

    Using a custom set for the demo:

    #FILE LISTBOX
    $sourceListBox = New-Object System.Windows.Forms.ListBox
    $sourceListBox.SelectionMode = "MultiSimple"
    $sourceListBox.Size = New-Object System.Drawing.Size(250,310)
    $sourceListBox.Location = New-Object System.Drawing.Point(20,30)
    $sourceListBox.Items.AddRange(@('hello', 'world', 'foo', 'bar', 'baz'))
    $form.Controls.Add($sourceListBox)
    
    #TOOLTIP
    $toolTip = New-Object System.Windows.Forms.ToolTip
    $tracker = [System.Collections.Generic.List[int]]::new()
    $sourceListBox.Add_SelectedIndexChanged({
        $indices = [int[]] $sourceListBox.SelectedIndices
        $tracker.RemoveAll({ -not $sourceListBox.SelectedIndices.Contains($args[0]) })
        $tracker.AddRange([System.Linq.Enumerable]::Except($indices, $tracker))
    
        if ($tracker.Count) {
            $lastSelected = $sourceListBox.Items[$tracker[-1]]
            $toolTip.SetToolTip($this, "Selected Item: $lastSelected")
        }
    })
    

    demo