Winform objListBox 除非在终端中粘贴变量,否则不会加载

Winform objListBox Won't load unless Variable Pasted in Terminal

我以前从来没有遇到过这样的问题。我已经尝试了很多方法来解决这个问题,但无法解决。 除非在 Powershell-ISE 中我在执行之前在终端中键入 $Qlfile = "C:\querylist",否则我无法填充此 objListBox。

$QlFile = "C:\querylist.txt"

Add-Type -assembly System.Windows.Forms
[reflection.assembly]::loadwithpartialname("System.Drawing") | Out-Null
$objForm = New-Object System.Windows.Forms.Form
$objForm.Size = New-Object System.Drawing.Size(850,550)
$objForm.StartPosition = "WindowsDefaultLocation"
$objForm.Text = "Query List"
$objForm.AutoScroll = $True
$objListBox = New-Object System.Windows.Forms.ListBox
$objListBox.Location = New-Object System.Drawing.Size(10,40)
$objListBox.Size = New-Object System.Drawing.Size(800,30)
$objListBox.ScrollAlwaysVisible = $True
$objListBox.Height = 250
$objListBox.add_SelectedIndexChanged($SelectedFile)
$objListBox.DrawMode = [System.Windows.Forms.DrawMode]::OwnerDrawFixed
$objListBox.Add_DrawItem($objListBox_DrawItem)
$objForm.Controls.Add($objListBox)
$objTextBox = New-Object System.Windows.Forms.TextBox
$objTextBox.Location = New-Object System.Drawing.Size(10,320)
$objTextBox.Size = New-Object System.Drawing.Size(800,3000)
$objtextBox.Height = 100
$objtextBox.Multiline = $true
$objForm.Controls.Add($objtextBox)
# create label
$labelz1 = New-Object system.Windows.Forms.Label
$labelz1.Text = "Select a Query"
$labelz1.Left=10
$labelz1.Top= 20
$labelz1.Font= "Verdana"

$labelz2 = New-Object system.Windows.Forms.Label
$labelz2.Text = "Edit Query"
$labelz2.Left=10
$labelz2.Top= 300
$labelz2.Font= "Verdana"

#add the label to the form
$objForm.controls.add($labelz1)
$objForm.controls.add($labelz2)

$BigButton = New-Object System.Windows.Forms.Button
$BigButton.Size = New-Object System.Drawing.Size(250,50)
$BigButton.Location = New-Object System.Drawing.Size(10,450)
$BigButton.Add_MouseHover({$BigButton.backcolor = [System.Drawing.Color]::CornflowerBlue
            $BigButton.Text = "CLICK ME!"})
$BigButton.Add_MouseLeave({$BigButton.backcolor = [System.Drawing.Color]::DarkBlue
            $BigButton.Text = "Copy Text"})
$BigButton.Text = "Copy Text"

$BigButton.Add_Click({
    #$objtextBox.Text | Clip
    $WPFQuery_text.text = $objtextBox.Text
    })
$objForm.controls.add($BigButton)

$InitialFormWindowState = New-Object System.Windows.Forms.FormWindowState
# Populate list.
Get-Content $QlFile | ForEach-Object {[void] $objListBox.Items.Add($_)}

$objListBox_DrawItem={
 param(
  [System.Object] $sender,
  [System.Windows.Forms.DrawItemEventArgs] $e
 )
   #Suppose Sender de type Listbox
 if ($Sender.Items.Count -eq 0) {return}

   #Suppose item de type String
 $lbItem=$Sender.Items[$e.Index]
 if ( $lbItem.contains('Q:'))  
 {
    $Color=[System.Drawing.Color]::Orange      
    try
    {
      $brush = new-object System.Drawing.SolidBrush($Color)
      $e.Graphics.FillRectangle($brush, $e.Bounds)
    }
    finally
    {
      $brush.Dispose()
    }
   }
 $e.Graphics.DrawString($lbItem, $e.Font, [System.Drawing.SystemBrushes]::ControlText, (new-object System.Drawing.PointF($e.Bounds.X, $e.Bounds.Y)))
}    


$SelectedFile=
{
$objtextBox.Text = ($objListbox.SelectedItem)
}


$OnLoadForm_StateCorrection=
{#Correct the initial state of the form to prevent the .Net maximized form issue
    $objForm.WindowState = $InitialFormWindowState
}

#Save the initial state of the form
$InitialFormWindowState = $objForm.WindowState
#Init the OnLoad event to correct the initial state of the form
$objForm.add_Load($OnLoadForm_StateCorrection)
#Show the Form

[System.Windows.Forms.Application]::Run($objForm)
#$objForm.ShowDialog()

有趣的是,我什至不需要按回车键。只需输入 $QlFile 然后删除即可。
没有任何意义。
如果我右键单击 .ps1 文件,然后使用 Powershell 运行 它永远不会工作,因为我猜它没有存储在 session/thread 中的 $QLfile 目标。

我必须使用 [System.Windows.Forms.Application]::运行($objForm) 因为我 运行 这在一个线程中与另一个 WPF 表单并排(上面未显示) ) 所有这些代码都在一个按钮内:$WPFbutton3.Add_Click({ }) 但我将它作为一个单独的 .ps1 来编写,以使其首先工作。
我需要能够同时编辑和 select。使用 .ShowDialog.

不可能做到这一点

我想解决方案是以某种方式将变量 $Qlfile 放在 [System.Windows.Forms.Application]::运行() 运行 所在的 thread/job 中。

你是怎么做到的?

我试过:

$ps = [powershell]::create()
$ps.AddScript(
     {
     [System.Windows.Forms.Application]::Run($objForm)
     })
$ps.Runspace.SessionStateProxy.SetVariable("form", $objForm)
$ps.BeginInvoke()

但它不起作用,因为它是后台进程,所以我根本看不到winform。

感谢阅读,请多多指教

您需要在使用事件处理程序之前定义它们。将 $SelectedFile$OnLoadForm_StateCorrection 的定义移动到顶部。

这是我的版本:

[CmdletBinding()]
param(
    $SourceFile = "C:\querylist.txt"
)
Add-Type -Assembly System.Windows.Forms, System.Drawing

$MainForm = [System.Windows.Forms.Form]@{
    Size          = New-Object System.Drawing.Size(850, 550)
    StartPosition = "WindowsDefaultLocation"
    Text          = "Query List"
    AutoScroll    = $True
}

$ListBox = [System.Windows.Forms.ListBox]@{
    Location            = New-Object System.Drawing.Size(10, 40)
    Size                = New-Object System.Drawing.Size(800, 30)
    ScrollAlwaysVisible = $True
    Height              = 250
    DrawMode            = "OwnerDrawFixed"
}
$MainForm.Controls.Add($ListBox)


$TextBox = [System.Windows.Forms.TextBox]@{
    Location  = New-Object System.Drawing.Size(10, 320)
    Size      = New-Object System.Drawing.Size(800, 3000)
    Height    = 100
    Multiline = $true
}
$MainForm.Controls.Add($TextBox)

$selectLabel = [System.Windows.Forms.Label]@{
    Text = "Select a Query"
    Left = 10
    Top  = 20
    Font = "Verdana"
}
$MainForm.Controls.add($selectLabel)

$EditLabel = [System.Windows.Forms.Label]@{
    Text = "Edit Query"
    Left = 10
    Top  = 300
    Font = "Verdana"
}
$MainForm.Controls.add($EditLabel)

$BigButton = [System.Windows.Forms.Button]@{
    Size     = New-Object System.Drawing.Size(250, 50)
    Location = New-Object System.Drawing.Size(10, 450)
    Text     = "Copy Text"
}
$MainForm.controls.add($BigButton)

$ListBox.Add_SelectedIndexChanged( {
        $TextBox.Text = ($ListBox.SelectedItem)
    })

# Hook up event handlers
$ListBox.Add_DrawItem( {
    param(
        [System.Object] $sender,
        [System.Windows.Forms.DrawItemEventArgs] $e
    )
    #Suppose Sender de type Listbox
    if ($Sender.Items.Count -eq 0) {
        return
    }

    #Suppose item de type String
    $lbItem = $Sender.Items[$e.Index]
    if ( $lbItem.contains('Q:')) {
        $Color = [System.Drawing.Color]::Orange
        try {
            $brush = new-object System.Drawing.SolidBrush($Color)
            $e.Graphics.FillRectangle($brush, $e.Bounds)
        } finally {
            $brush.Dispose()
        }
    }
    $e.Graphics.DrawString($lbItem, $e.Font, [System.Drawing.SystemBrushes]::ControlText, (new-object System.Drawing.PointF($e.Bounds.X, $e.Bounds.Y)))
})

$BigButton.Add_MouseHover( {
    $BigButton.backcolor = [System.Drawing.Color]::CornflowerBlue
    $BigButton.Text = "CLICK ME!"
})
$BigButton.Add_MouseLeave( {
    $BigButton.backcolor = [System.Drawing.Color]::DarkBlue
    $BigButton.Text = "Copy Text"
})
$BigButton.Add_Click( {
    #$TextBox.Text | Clip
    $WPFQuery_text.text = $TextBox.Text
})

# Save the initial state of the form
$InitialFormWindowState = $MainForm.WindowState
# Init the OnLoad event to correct the initial state of the form
$MainForm.Add_Load( {
    #Correct the initial state of the form to prevent the .Net maximized form issue
    $MainForm.WindowState = $InitialFormWindowState
})

# Populate list.
Get-Content $SourceFile | ForEach-Object {[void] $ListBox.Items.Add($_)}

#Show the Form
[System.Windows.Forms.Application]::Run($MainForm)