【问题标题】:ListView Sort doesn't work OnClick (PowerShell)ListView 排序不起作用 OnClick (PowerShell)
【发布时间】:2016-06-22 15:24:23
【问题描述】:

我在 PowerShell 中构建的表单上有一个 ListView,但我无法对其进行排序。

如果我从命令行调用 $LV.Sort()(虽然没有显示表单),它工作得非常好。但是,如果我尝试在表单上的任何内容上的 OnClick 事件中调用它,它不会。我已经设置了标志,并且我知道那段代码正在运行,它只是没有做任何事情或标记任何错误。

显然$LV.Sorting = "Ascending" 已设置,否则它根本不会排序,我可以更改项目以便对 ListView 的引用很好。还尝试在出现线程问题时调用,但没有什么不同。

令人讨厌的是,由于很多人忘记设置 Sorting 属性,这是一个棘手的研究课题。

编辑:不确定是否相关,但使用 ShowDialog() 调用表单

Add-Type -AssemblyName System.Windows.Forms
[System.Windows.Forms.Application]::EnableVisualStyles()

$form = New-Object System.Windows.Forms.Form
$LVserverlist = New-Object System.Windows.Forms.ListView
$form.Controls.Add($LVserverlist)
    $LVserverlist.Dock = "Fill"
    $LVserverlist.View = "Details"
    $LVserverlist.Sorting = "Ascending"
    $LVserverlist.Add_ColumnClick({ $LVserverlist.sort(); $LVserverlist.Items[0].Text = "Working?" })
    $LVserverlist.Columns.Add("Name", 200, "Left") | Out-Null

0..10 | Foreach-Object {
    $LVItem = New-Object System.Windows.Forms.ListViewItem
    $LVItem.Text = (Get-Random -Maximum 1000).ToString()
    $LVserverlist.Items.Add($LVItem) | Out-Null
}

$form.ShowDialog()

【问题讨论】:

  • 可能是范围问题。请向我们展示您的代码
  • 我有大约一千行代码。所有相关的是 ListView 位于 Form 内的 Splitter 内的 Splitter 中,以ShowDialog() 显示。如果我将Sort() 添加到任何 OnClick 事件中,它什么也不做,但事件中的其余代码运行良好。将ListView作为参数传递或使用全局引用都没有关系,我可以在其中添加和更改项目。
  • 制作一个能重现错误的小应用程序,然后发布:)(请参阅the MVCE section of the Help Center
  • 添加了复制问题的代码。单击列,第一项更改为“工作?”正如预期的那样,但没有排序。关闭表单,在提示符下调用$LVserverlist.Sort(),再次显示表单,列表排序。

标签: winforms sorting listview powershell


【解决方案1】:

从来没有找到让 Sort() 工作的解决方案,最终得到了这个解决方法(无论如何它更灵活一点):

Param
(
    [System.Windows.Forms.ListView]$sender,
    $column
)
$temp = $sender.Items | Foreach-Object { $_ }

$sender.Items.Clear()
$sender.Items.AddRange(($temp | Sort-Object -Property @{ Expression={ $_.SubItems[$column].Text } }))

请注意,在 ListView 上,Sorting 属性需要设置为 None 否则项目将按字母顺序添加回来。

【讨论】:

    【解决方案2】:

    你可以试试自定义函数Sort-ListViewColumn

    $MyListView.Add_ColumnClick({
        param($sender,$e)
        # Sort as Text String (not [int])
        Sort-ListViewColumn -ListView $this -ColumnIndex $e.column
    })
    

    完整功能代码:

    function Sort-ListViewColumn
    {
        <#
        .SYNOPSIS
            Sort the ListView's item using the specified column.
        .DESCRIPTION
            Sort the ListView's item using the specified column.
            This function uses Add-Type to define a class that sort the items.
            The ListView's Tag property is used to keep track of the sorting.
        .PARAMETER ListView
            The ListView control to sort.
        .PARAMETER ColumnIndex
            The index of the column to use for sorting.
    
        .PARAMETER  SortOrder
            The direction to sort the items. If not specified or set to None, it will toggle.
    
        .EXAMPLE
            Sort-ListViewColumn -ListView $listview1 -ColumnIndex 0
    
        .NOTES
            SAPIEN Technologies, Inc.
            http://www.sapien.com/
    
    #>
        param (
            [ValidateNotNull()]
            [Parameter(Mandatory = $true)]
            [System.Windows.Forms.ListView]$ListView,
            [Parameter(Mandatory = $true)]
            [int]$ColumnIndex,
            [System.Windows.Forms.SortOrder]$SortOrder = 'None')
    
        if (($ListView.Items.Count -eq 0) -or ($ColumnIndex -lt 0) -or ($ColumnIndex -ge $ListView.Columns.Count))
        {
            return;
        }
    
        #region Define ListViewItemComparer
        try
        {
            $local:type = [ListViewItemComparer]
        }
        catch
        {
            Add-Type -ReferencedAssemblies ('System.Windows.Forms') -TypeDefinition  @" 
        using System;
        using System.Windows.Forms;
        using System.Collections;
        public class ListViewItemComparer : IComparer
        {
            public int column;
            public SortOrder sortOrder;
            public ListViewItemComparer()
            {
                column = 0;
                sortOrder = SortOrder.Ascending;
            }
            public ListViewItemComparer(int column, SortOrder sort)
            {
                this.column = column;
                sortOrder = sort;
            }
            public int Compare(object x, object y)
            {
                if(column >= ((ListViewItem)x).SubItems.Count)
                    return  sortOrder == SortOrder.Ascending ? -1 : 1;
    
                if(column >= ((ListViewItem)y).SubItems.Count)
                    return sortOrder == SortOrder.Ascending ? 1 : -1;
    
                if(sortOrder == SortOrder.Ascending)
                    return String.Compare(((ListViewItem)x).SubItems[column].Text, ((ListViewItem)y).SubItems[column].Text);
                else
                    return String.Compare(((ListViewItem)y).SubItems[column].Text, ((ListViewItem)x).SubItems[column].Text);
            }
        }
    "@ | Out-Null
        }
        #endregion
    
        if ($ListView.Tag -is [ListViewItemComparer])
        {
            #Toggle the Sort Order
            if ($SortOrder -eq [System.Windows.Forms.SortOrder]::None)
            {
                if ($ListView.Tag.column -eq $ColumnIndex -and $ListView.Tag.sortOrder -eq 'Ascending')
                {
                    $ListView.Tag.sortOrder = 'Descending'
                }
                else
                {
                    $ListView.Tag.sortOrder = 'Ascending'
                }
            }
            else
            {
                $ListView.Tag.sortOrder = $SortOrder
            }
    
            $ListView.Tag.column = $ColumnIndex
            $ListView.Sort()#Sort the items
        }
        else
        {
            if ($Sort -eq [System.Windows.Forms.SortOrder]::None)
            {
                $Sort = [System.Windows.Forms.SortOrder]::Ascending
            }
    
            #Set to Tag because for some reason in PowerShell ListViewItemSorter prop returns null
            $ListView.Tag = New-Object ListViewItemComparer ($ColumnIndex, $SortOrder)
            $ListView.ListViewItemSorter = $ListView.Tag #Automatically sorts
        }
    }
    

    【讨论】:

    • 你成就了我的一天!我一直在寻找一些提示来编写自己的内容,并找到了一个完全可行的解决方案!只是让人们知道这个解决方案有效。
    【解决方案3】:

    coller 事件

    $MyListView.add_ColumnClick({SortListView $this $_.Column})
    

    排序功能可以记住最新的订单:

    function SortListView {
        Param(
            [System.Windows.Forms.ListView]$sender,
            $column
        )
        $temp = $sender.Items | Foreach-Object { $_ }
        $Script:SortingDescending = !$Script:SortingDescending
        $sender.Items.Clear()
        $sender.ShowGroups = $false
        $sender.Sorting = 'none'
        $sender.Items.AddRange(($temp | Sort-Object -Descending:$script:SortingDescending -Property @{ Expression={ $_.SubItems[$column].Text } }))
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-12
      相关资源
      最近更新 更多