You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PowerShell中ListView单双击事件无冲突实现及Task.Delay用法疑问

解决WinForms ListView单双击冲突的PowerShell实现

一、await Task.Delay与Start-Sleep的核心区别

  • Start-Sleep是同步阻塞:执行时会卡住当前线程(如果是UI线程,界面会彻底失去响应),直到等待结束。
  • await Task.Delay(SystemInformation.DoubleClickTime)是异步等待:不会阻塞UI线程,等待期间界面仍可正常交互,同时能监听后续的点击事件——这正是区分单双击的关键:等待系统设定的双击时间间隔,判断这段时间内是否出现第二次点击,以此决定触发单点击还是双点击逻辑。

二、PowerShell完整实现代码

以下是适配WinForms ListView大图模式的单双击事件代码,完美避免冲突:

Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing

# 创建主窗体
$mainForm = New-Object System.Windows.Forms.Form
$mainForm.Text = "ListView单双击测试"
$mainForm.Size = New-Object System.Drawing.Size(600, 400)

# 初始化ListView(大图模式)
$listView = New-Object System.Windows.Forms.ListView
$listView.Dock = [System.Windows.Forms.DockStyle]::Fill
$listView.View = [System.Windows.Forms.View]::LargeIcon
$listView.LargeImageList = New-Object System.Windows.Forms.ImageList
$listView.LargeImageList.ImageSize = New-Object System.Drawing.Size(48, 48)

# 添加测试项目(带图标)
for ($i = 1; $i -le 10; $i++) {
    $listItem = New-Object System.Windows.Forms.ListViewItem("测试项$i")
    # 提取PowerShell图标作为示例,可替换为自定义图标
    $itemIcon = [System.Drawing.Icon]::ExtractAssociatedIcon((Get-Command powershell.exe).Source)
    $listView.LargeImageList.Images.Add($itemIcon)
    $listItem.ImageIndex = $i - 1
    $listView.Items.Add($listItem)
}

# 单双击状态追踪变量
$clickCounter = 0

# 鼠标点击事件处理器
$listView.Add_MouseClick({
    param($sender, $e)
    $global:clickCounter++

    # 第一次点击时启动后台等待逻辑
    if ($clickCounter -eq 1) {
        $null = [System.Threading.Tasks.Task]::Run({
            # 等待系统设定的双击间隔时间
            Start-Sleep -Milliseconds [System.Windows.Forms.SystemInformation]::DoubleClickTime
            
            # 根据最终点击次数判断触发事件
            if ($global:clickCounter -eq 1) {
                # 单点击:通过Invoke确保UI操作在主线程执行
                $sender.Invoke([Action]{
                    [System.Windows.Forms.MessageBox]::Show("单点击:$($sender.SelectedItems[0].Text)", "操作提示")
                })
            } else {
                # 双点击
                $sender.Invoke([Action]{
                    [System.Windows.Forms.MessageBox]::Show("双点击:$($sender.SelectedItems[0].Text)", "操作提示")
                })
            }
            # 重置计数,准备下一轮判断
            $global:clickCounter = 0
        })
    }
})

# 组装控件并显示窗体
$mainForm.Controls.Add($listView)
$mainForm.ShowDialog() | Out-Null

代码逻辑说明

  1. 用clickCounter记录短时间内的点击次数,第一次点击后启动后台任务等待系统双击间隔
  2. 后台任务等待期间,UI线程保持响应,若用户触发第二次点击,clickCounter会变为2
  3. 等待结束后,根据clickCounter的值触发对应事件,同时重置计数
  4. 用$sender.Invoke确保弹窗等UI操作在主线程执行,避免跨线程异常

内容的提问来源于stack exchange,提问作者Joe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 15:55:10