这里是新用户。我不做任何编程/编码的贸易和有限的教育经验,所以我知道的大部分是从修修补补。我正在编写一个PowerShell脚本,构建一个GUI,并有一些麻烦更新一个GUI项目的基础上编辑另一个GUI项目。我已经简化了它,以显示我的问题。
下面是调用的函数:
function GUITitleTextBox_TextChanged
{
[CmdletBinding()]
param
(
[parameter(Mandatory=$True, Position=0)][System.Object] $Sender,
[parameter(Mandatory=$True, Position=1)][System.EventArgs] $EventArguments,
[parameter(Mandatory=$True, Position=2)][String] $Text,
[parameter(Mandatory=$False, Position=3)][System.Object] $ControlToUpdate
)
Write-Host $Sender.Text
Write-Host $Text
Write-Host $ControlToUpdate.Text
}
字符串
下面是创建对象和添加事件的相关代码:
#Add the GUI Title textbox
$GUITitleTextBox = New-Object System.Windows.Forms.TextBox
$GUITitleTextBox.Text = "Default Form"
$GUITitleTextBox.Width = 240
$GUITitleTextBox.Add_TextChanged({GUITitleTextBox_TextChanged -Sender $this -EventArguments $_ -Text $this.Text -ControlToUpdate $GUITitleTextBox}) #Add an event when text changes.
$Form.Controls.Add($GUITitleTextBox) #Add the textbox to the Form
型
下面是控制台的输出:
Default For
Default For
Default Fo
Default Fo
Default F
Default F
型
使用$this传递给函数的任何东西都可以正常工作,就像两个Write-Host命令发送数据一样,但是当传递带有变量名($GUITitleTextBox)的对象时,它就不起作用了。我可以在创建对象的代码下面直接添加一个Write-Host $GUITitleTextBox.Text。如果在声明和示例化$GUITitleTextBox时,我执行$script:GUITitleTextBox将作用域设置为整个脚本,那么我当然可以更改Text属性。
更复杂的是,在另一个脚本上,我可以按照相同的格式将Windows窗体对象传递给一个函数。
其他脚本的函数:
function ContainerDimensionControlChanged()
{
[CmdletBinding()]
param
(
[parameter(Mandatory=$True, Position=0)] [System.Object] $CallingControl,
[parameter(Mandatory=$True, Position=1)] [System.Object] $Container,
[parameter(Mandatory=$True, Position=2)] [string] $Axis,
[parameter(Mandatory=$False, Position=3)][System.Object] $ControlToUpdate
)
<Removed because it's not relevant>
$ControlToUpdate.Value = $Container.$Axis
}
型
下面是调用它的代码($Panel和$WidthTextBox都是在运行此代码的同一函数中较早/较晚创建的其他表单元素):
$WidthSlider = New-Object System.Windows.Forms.TrackBar
$WidthSlider.Top = 45
$WidthSlider.Left = 330
$WidthSlider.Name = "WidthSlider"
$WidthSlider.AutoSize = $true
$WidthSlider.Minimum = 5
$WidthSlider.Maximum = 750
$WidthSlider.Value = $PanelDefaultWidth
$WidthSlider.Add_ValueChanged({ContainerDimensionControlChanged $This $Panel "Width" $WidthTextBox})
型
那么为什么第二个工作,而第一个不工作?我错过了什么?
1条答案
按热度按时间hm2xizp91#
PowerShell的
$this
变量在事件处理程序的脚本块中使用时并不总是您所期望的。在你的第一个脚本中,
$this
并没有引用$GUITitleTextBox
,而是引用了脚本块运行的上下文,而不是你的文本框,这就是为什么它没有按预期工作。相反,使用$sender
,它被传递给函数并引用了引发事件的控件。下面是更正后的事件处理程序添加行:
字符串
根据评论更新
在PowerShell中,当您在事件中使用脚本块(匿名函数)时,在事件注册时不会捕获其中使用的变量,除非您强制它们与
use
语句一起使用或通过适当地确定它们的范围。以下是如何正确地将$ControlToUpdate
传递给事件处理程序中的函数:GetNewClosure()
方法创建一个闭包,将变量的当前状态绑定到事件处理程序的脚本块。下面是完整的更正代码,以确保
$ControlToUpdate
被函数接收:型
通过使用
GetNewClosure()
,我们确保用作事件处理程序的脚本块捕获了$GUITitleTextBox
的当前状态,因此当文本更改时,它会将当前控制传递给函数。