Передача по ссылке, кажется, работает, но все еще генерирует ошибку? Как вернуть несколько значений из диалогового окна WinForms? - PullRequest
0 голосов
/ 29 июня 2018

Фон

Я пытаюсь создать WinForm, чтобы, когда пользователь нажимал кнопку «Отправить», все значения в функции «Отправить» возвращались основному, с которым нужно работать. В целях тестирования я просто пытался заставить $firstName работать. Чтобы сделать это, я пытался выяснить, передать ли справочные параметры.

Этот блок кода работает сам по себе:

$txtFirstName = New-Object system.Windows.Forms.TextBox
$txtFirstName.text = "John"

function Submit([ref]$firstName){ 
    $firstName.value =  $txtFirstName.Text 
}

$firstName = $null
Submit([ref]$firstName)
$firstName

Однако, когда я пытаюсь применить ту же концепцию к моему сценарию , кажется, что он работает НО Я все еще получаю ошибку.

Ошибка:

Свойство 'value' не может быть найдено для этого объекта; убедитесь, что он существует и может быть установлен.

Вот мой сценарий:

https://github.com/InconspicuousIntern/Form/blob/master/Form.ps1

Моя гипотеза:

  1. В PowerShell возникла проблема с передачей / назначением переменных во время работы.
  2. Мой сценарий вышел из строя (я не привык к функциям, которые должны быть определены первыми)

Ответы [ 2 ]

0 голосов
/ 30 июня 2018

Почему ваш оригинальный фрагмент работает и почему ваш связанный с ним полный сценарий не работа описана в моем ответе на ваш связанный вопрос .

Короче говоря: у вас был обработчик событий, который вызвал вашу Submit функцию без аргументов сначала, в добавление к , позже вызвав его правильно с аргументом , что вызвало проблему.


Что касается объяснения в ваш собственный ответ :

Ваш переставленный код работает только случайно :

Он присоединяет обработчик событий, содержащий некорректный, без аргументов Submit вызов после отображения диалогового окна, после чего он просто ничего не делает.


Как структурировать ваш код:

У вас есть два основных варианта, которые обычно объединяются :

  • Принять меры во время отображения диалогового окна , используя обработчики событий .

    • Вы присоединяете обработчики событий как блоки сценариев, передаваемые в методы .Add_<eventName>() отдельных элементов управления, как вы это делали в случае $btnSubmit.Add_Click({ ... }).

    • Предупреждение: блок сценария выполняется в области дочерних переменных , поэтому требуется дополнительная работа для изменения переменных в области действия вызывающего, например, с помощью спецификатора области script; например, $script:var (или даже с использованием подхода [ref], но это жестко).

  • Принять меры после закрытия диалога .

    • После этого вы можете просто напрямую получить доступ к свойствам элементов управления формы.

Следующий автономный фрагмент демонстрирует обе техники:

Add-Type -AssemblyName System.Windows.Forms

# Create the form.
$form = New-Object system.Windows.Forms.Form -Property @{
    ClientSize      = New-Object System.Drawing.Point 400,100
    Text            = "Dialog Demo"
}    

# Create the controls and add them to the form.
$form.Controls.AddRange(@(
    New-Object system.Windows.Forms.Label -Property @{
        Text           = "First Name:"
        AutoSize       = $true
        Location       = New-Object System.Drawing.Point 10,20
        Font           = 'Microsoft Sans Serif,10'
    }

    ($txtFirstName = New-Object system.Windows.Forms.TextBox -Property @{
        Width          = 250
        Location       = New-Object System.Drawing.Point 100, 20
    })

    ($btnSubmit = New-Object system.Windows.Forms.Button -Property @{
        Text              = "Submit"
        Location          = New-Object System.Drawing.Point 160, 60
    })
))


# Attach an event handler to the first-name field.
$txtFirstName.Add_KeyPress({ param($obj, $evArgs)
    # Example: Convert every character typed to uppercase. 
    $evArgs.KeyChar = [char]::ToUpper($evArgs.KeyChar)
})

# Make pressing Enter the same as clicking the Submit button.
$form.AcceptButton = $btnSubmit
# Make the Submit button act like an OK button, which means:
#  - auto-close the form
#  - make .ShowDialog() return [System.Windows.Forms.DialogResult]::OK
$btnSubmit.DialogResult = [System.Windows.Forms.DialogResult]::OK

# Show the form synchronously (during which event handlers may fire)
# and take action based on the return value, which is
# a [System.Windows.Forms.DialogResult] enumeration value that
# reflects the button used to close the form.
if ($form.ShowDialog() -eq 'OK') { # Dialog was confirmed.

    # You can now access the controls' properties as needed.
    # In this example we output a custom object that contains
    # the first name; this can easily be extended to include
    # other properties
    [pscustomobject] @{
        FirstName = $txtFirstName.Text 
    }

} else { # Dialog was canceled.
    Write-Warning "Dialog canceled."
}
0 голосов
/ 29 июня 2018

Ответ: Компоненты скрипта вышли из строя.

Необходимо быть:

function Submit(){...}

<form fields>

[void]$NewUserForm.ShowDialog()
Submit([ref]$firstName)
$btnSubmit.Add_Click({ Submit }) #GUI event
$firstName

Вместо:

function Submit(){...}

<form fields>

$btnSubmit.Add_Click({ Submit }) #GUI event
[void]$NewUserForm.ShowDialog()
Submit([ref]$firstName)  
$firstName

Если у кого-нибудь есть ссылки, где я могу узнать больше о том, как заказать мои сценарии и методы для этого, я был бы благодарен.

...