Winforms Powershell窗体-如何添加上下文菜单事件处理程序,以防止在未选择项时打开?

Winforms Powershell窗体-如何添加上下文菜单事件处理程序,以防止在未选择项时打开?,winforms,powershell,Winforms,Powershell,我有一个带有listview的表单,它有一个右键单击的上下文菜单。我希望菜单仅在右clikc位于listview中所选项目的上方时出现-此时它出现在listview窗口中的任何位置,即使未选择任何内容 Add-Type -AssemblyName System.Windows.Forms $form = New-Object System.Windows.Forms.Form $form.Text = "Foo" $form.Size = '400,400' $CMitemEnable =

我有一个带有listview的表单,它有一个右键单击的上下文菜单。我希望菜单仅在右clikc位于listview中所选项目的上方时出现-此时它出现在listview窗口中的任何位置,即使未选择任何内容

Add-Type -AssemblyName System.Windows.Forms

$form = New-Object System.Windows.Forms.Form
$form.Text = "Foo"
$form.Size = '400,400'

$CMitemEnable = New-Object System.Windows.Forms.ToolStripMenuItem
$CMitemEnable.Text = 'Enable'
$CMitemDisable = New-Object System.Windows.Forms.ToolStripMenuItem
$CMitemDisable.Text = 'Disable'
$lvcontextmenu = New-Object System.Windows.Forms.ContextMenuStrip
$lvcontextmenu.ShowImageMargin = $false
$lvcontextmenu.Items.AddRange(@($CMitemEnable,$CMitemDisable))

$listviewbox = New-Object System.Windows.Forms.ListView
$listviewbox.View = [System.Windows.Forms.View]::Details
$listviewbox.Location = '15,20'
$listviewbox.Size = '340,150'
$listviewbox.Columns.Add('Host',180) | Out-Null
$listviewbox.FullRowSelect = $true
$listviewbox.MultiSelect = $false
# $listviewbox.ContextMenuStrip = $lvcontextmenu

$InfoText = New-Object System.Windows.Forms.TextBox
$InfoText.Location = '15,180'
$InfoText.Size = '340,120'
$InfoText.Multiline = $true
$InfoText.ScrollBars = "Vertical"
$InfoText.ReadOnly = $true

$form.Controls.AddRange(@($listviewbox,$InfoText))

$listviewbox.Items.AddRange(@('Foobar1','foobar2'))


$listviewbox.Add_MouseDown({
    $listviewbox.contextmenustrip = $null
    If($listviewbox.SelectedItems.Count){
        $listviewbox.contextmenustrip = $lvcontextmenu
        $InfoText.AppendText("`r`n" + ($this.SelectedItems[0].Text))
    }
    Else {
        $InfoText.AppendText("`r`nNothing selected")
        $listviewbox.contextmenustrip = $null
    }
})

# Show form
$form.ShowDialog() | Out-Null
$form.Dispose()

我以前没有做过上下文菜单,我一辈子都看不到如何实现此事件处理程序-有C等的示例,但有人能为我指出Powershell的正确方向吗?

也许有一种更简洁的方法,但这对我来说很有效:

首先,删除第22行(
$listviewbox.ContextMenuStrip=$lvcontextmenu
) 然后将
$listviewbox
的单击处理程序更改为:

$listviewbox.Add_Click({
    If($this.SelectedItems.Count){
        $this.ContextMenuStrip = $lvcontextmenu
        $InfoText.AppendText("`r`n" + ($this.SelectedItems[0].Text))
    }
    Else {
        $this.ContextMenuStrip = $null
        $InfoText.AppendText("`r`nNothing selected")
    }
})

下面的事件处理程序按照预期的方式工作-这是你们两人的提示组合,谢谢

$listviewbox.Add_MouseUp({
    $listviewbox.contextmenustrip = $null
    If($listviewbox.SelectedItems.Count){
        $listviewbox.contextmenustrip = $lvcontextmenu
        $InfoText.AppendText("`r`n" + ($this.SelectedItems[0].Text))
    }
    Else {
        $InfoText.AppendText("`r`nNothing selected")
        $listviewbox.contextmenustrip = $null
    }
})

考虑到以下几点:

  • 不要为
    列表视图设置
    ContextMenuStrip
  • 处理
    MouseClick
    事件,因此首先选择项目,然后运行代码。(另一种选择是,如果您喜欢鼠标按下,则需要将逻辑放入
    BeginInvoke
    中,以确保它在选择项目后运行。)
  • 使用所选项目的
    GetBound
    方法和
    e.Location
    ,检查单击的位置是否在项目矩形内
  • 通过传递
    光标,使用
    Show
    显示
    ContextMenuStrip
    。位置
以下是一个工作示例:

Add-Type -AssemblyName System.Windows.Forms

$form = New-Object System.Windows.Forms.Form
$form.Text ="Test"
$form.Controls.AddRange(@(
    ($listView1 = [System.Windows.Forms.ListView] @{
        Dock = [System.Windows.Forms.DockStyle]::Fill;
        FullRowSelect = $true;
        View = [System.Windows.Forms.View]::Details;
    })
))
$contextMenuStrip1 = [System.Windows.Forms.ContextMenuStrip]@{}
$listView1.Columns.Add("C1") | Out-Null
$listView1.Columns.Add("C2") | Out-Null
$listView1.Items.Add("Item1") | Out-Null
$listView1.Items.Add("Item2") | Out-Null
$contextMenuStrip1.Items.Add("Menu 1") | Out-Null
$contextMenuStrip1.Items.Add("Menu 2") | Out-Null

$listView1.Add_MouseClick({param($sender,$e)
    if ($e.Button -eq [System.Windows.Forms.MouseButtons]::Right){
        if ($listView1.FocusedItem.GetBounds(
            [System.Windows.Forms.ItemBoundsPortion]::Entire).Contains($e.Location)){
            $contextMenuStrip1.Show([System.Windows.Forms.Cursor]::Position)
        }
    } 
})
$form.ShowDialog() | Out-Null
$form.Dispose()
$contextMenuStrip1.Dispose()

如果在listview中未选择任何内容,则上下文菜单仍会出现-您可以右键单击listview中的任何位置,但它仍会出现-这正是我试图避免的。@怀疑论者忘了提到您应该先删除第22行
$listviewbox.ContextMenuStrip=$lvcontextmenu
。抱歉..是的-我这样做了-但是它只在第一次工作,如果你右键单击一个项目,那么上下文菜单总是出现在你在列表视图中单击的任何地方。不太确定我应该使用单击事件,使用上下文菜单事件检查可能更干净?@怀疑论者嗯。。。明白你的意思了。恐怕回到绘图板上..窗体的
鼠标向下
$this.ContextMenuStrip=$listviewbox.SelectedItems.Count>0$lvcontextmenu:null。如果您确实想使用
$this
。否则,只需ListView的
MouseDown
事件。已更新-这似乎更接近,但仍然不是预期的wokring,在选中某个项目后在空白处第一次右键单击仍然会显示上下文菜单。非常好,我确信有更好的方法,这说明了很多问题,也意味着它忽略了列标题。非常感谢。