Получить имя родителя - PullRequest
3 голосов
/ 14 февраля 2020

С помощью какого метода или переменной я могу узнать имя родительского объекта в этом примере? То есть во время наведения мыши на первую кнопку, получите имя $ GetParentName = "Button01", второе $ GetParentName = "Button02", третье $ GetParentName = "Button03". $ GetParentName равно [string].

Если вместо переменной $GetParentName применить $This, то переменная $This позволяет получить значения объекта, но не получает имя предмет. Но как получить название объекта? Спасибо

Отредактировано: без использования $ This.Name.

$A = @{

    Main = [System.Windows.Forms.Form] @{ StartPosition = 'CenterParent' }

    Button01 = [System.Windows.Forms.Button] @{ Top = 0 }
    Button02 = [System.Windows.Forms.Button] @{ Top = 30 }
    Button03 = [System.Windows.Forms.Button] @{ Top = 60 }
}

$Script = { Write-host $GetParentName }

1..3 | % {

    $A["Button0$_"].Add_MouseEnter($Script)

    $A.Main.Controls.Add($A["Button0$_"])
}

[void]$A.Main.ShowDialog()

Ответы [ 2 ]

3 голосов
/ 14 февраля 2020

Вам необходимо установить свойство .Name для элементов управления кнопки, если вы хотите получить их имена внутри скрипта MouseEnter:

Add-Type -AssemblyName System.Windows.Forms

$A = @{

    Main = [System.Windows.Forms.Form] @{ StartPosition = 'CenterParent' }

    Button01 = [System.Windows.Forms.Button] @{ Top = 0  ; Name = 'Button01'}
    Button02 = [System.Windows.Forms.Button] @{ Top = 30 ; Name = 'Button02'}
    Button03 = [System.Windows.Forms.Button] @{ Top = 60 ; Name = 'Button03'}
}

$Script = { Write-host $this.Name }

1..3 | ForEach-Object {

    $A["Button0$_"].Add_MouseEnter($Script)

    $A.Main.Controls.Add($A["Button0$_"])
}

[void]$A.Main.ShowDialog()

$A.Main.Dispose()


Редактировать

Создание и присвоение имен кнопкам внутри ForEach-Object l oop может сэкономить вам ввод имени каждой кнопки:

Add-Type -AssemblyName System.Windows.Forms

$A = @{
    Main = [System.Windows.Forms.Form] @{ StartPosition = 'CenterParent' }
}

$Script = { Write-host $this.Name }

1..3 | ForEach-Object {
    $A["Button0$_"] = [System.Windows.Forms.Button] @{ Top = ($_ -1) * 30 ; Name = "Button0$_"}
    $A["Button0$_"].Add_MouseEnter($Script)

    $A.Main.Controls.Add($A["Button0$_"])
}

[void]$A.Main.ShowDialog()

$A.Main.Dispose()
2 голосов
/ 14 февраля 2020

Как Тео указывает в своем ответе , вам нужно назвать объекты ваших кнопок, присвоив их .Name свойству .

, чтобы избежать именования ваших кнопок дважды - один раз как имя свойства в вашей хеш-таблице, а затем снова через свойство .Name - вы можете создать кнопки в виде массива , что упрощает Общее решение:

$A = @{

    Main = [System.Windows.Forms.Form] @{ StartPosition = 'CenterParent' }

    # Create an *array* of buttons
    Buttons = [System.Windows.Forms.Button] @{ Top = 0; Name = 'Button1' },
              [System.Windows.Forms.Button] @{ Top = 30; Name = 'Button2' },
              [System.Windows.Forms.Button] @{ Top = 60; Name = 'Button3' }
}

# Print the name of the button being moused over.
$Script = { $this.Name | Out-Host }

# Attach the event-handler script block to each button.
$A.Buttons | % {

    $_.Add_MouseEnter($Script)

}

# Add the buttons to the form.
$A.Main.Controls.AddRange($A.Buttons)

$null = $A.Main.ShowDialog()

Если вы хотите избежать присвоения .Name свойству , вы можете использовать следующий подход:

Используйте PowerShell ETS (Extended Type System), чтобы добавить ключ записи хеш-таблицы, в которой каждая кнопка хранится как a пользовательское свойство (* экземпляр элемента NoteProperty), используя Add-Member, который может запросить скрипт обработчика событий:

Add-Type -AssemblyName System.Windows.Forms

$A = @{

    Main = [System.Windows.Forms.Form] @{ StartPosition = 'CenterParent' }

    Button01 = [System.Windows.Forms.Button] @{ Top = 0 }
    Button02 = [System.Windows.Forms.Button] @{ Top = 30 }
    Button03 = [System.Windows.Forms.Button] @{ Top = 60 }
}

$Script = {
    # Access the custom .CustomParent property added to each button instance below.
    Write-Host $this.CustomParent
}

1..3 | % {

    $key = "Button0$_"
    $btn = $A[$key]
    # Add a .CustomParent NoteProperty member to the button object
    # storing the key of the hashtable entry in which that button is stored.
    $btn | Add-Member -NotePropertyMembers @{ CustomParent = $key }

    $btn.Add_MouseEnter($Script)

    $A.Main.Controls.Add($btn)
}

[void]$A.Main.ShowDialog()

Что касается того, почему PowerShell не предоставляет и не должен предоставлять автоматическую c (встроенную) переменную например $GetParentName для поддержки этого сценария:

Существует два несвязанных мира, в которые вовлечено в этом сценарии:

  • переменные PowerShell

  • . NET типы из пространства имен System.Windows.Forms (WinForms)

WinForms не зависит от языка c - любой. NET язык может использовать его; все, что он знает, это то, как экземпляры его типов вкладываются во время выполнения и как вызывать соответствующие. NET события, как правило, в ответ на пользовательские события.

исходный объект события как сообщается в WinForms, отображается как $this в блоке сценария PowerShell, действующем как делегат события. NET, вызываемый непосредственно WinForms.

WinForms (по праву) не знает, какая структура данных или переменная на стороне PowerShell объект, в котором происходит событие, хранится в.

Даже на стороне PowerShell это полностью на ваше усмотрение - вы могли выбрать отдельные переменные, например, или массив, как показано выше, поэтому здесь нет общего шаблона , который может поддерживать автоматическая переменная c.

В данном случае PowerShell сам не может знать, что ваш блок $Script оказался косвенно связанный с экземпляром кнопки , случайно сохраненным в записи хеш-таблицы .

...