Как подтвердить изменения данных в графическом интерфейсе DataGridView (PowerShell)?

В моем случае я хочу использовать скрипт PS для создания WinForm с некоторыми элементами, включая DGV, содержащую 3 столбца (#, Page_Name, shrt). Первая строка должна быть строкой шаблона со значениями по умолчанию (1; индекс; NDX), поэтому я получаю ее из CSV-файла.
Мой код:

$DataGridView1                    = New-Object system.Windows.Forms.DataGridView
$DataGridView1.location           = New-Object System.Drawing.Point(20,121)
$DataGridView1.Name               = "Page-List"
$DataGridView1.AllowUserToAddRowsChanged = $true
$DataGridView1.AllowUserToAddRows = $true
# $DataGridView1.DataBindings
$DataGridView1.width              = 363
$DataGridView1.height             = 150
$DataGridView1.ColumnCount = 3
$DataGridView1.ColumnHeadersVisible = $true
$DataGridView1.Columns[0].Name = '#'
$DataGridView1.Columns[0].Width = "40"
$DataGridView1.Columns[1].Name = "Page_Name"
$DataGridView1.Columns[1].Width = "205"
$DataGridView1.Columns[2].Name = "shrt"
$DataGridView1.Columns[2].Width = "75"
$DataGridView1.ReadOnly = $false
$DataGridView1.EditMode  = "EditOnEnter"
$templateROW = @(Import-Csv -Delimiter ";"  "C:\Users\vkons\OneDrive\Документы\PowerShell\Scripts\test\DGV\index.csv" -Header "#", "Page_Name", "shrt" )
$datatable = ($templateROW + $DataGridView1Rows)
$DataGridView1Data = $datatable

foreach ($Row in $DataGridView1Data){
    $DataGridView1.Rows.Add($Row.'#', $Row.Page_Name, $Row.shrt)
}

Если пользователь изменит значение ячеек Page_Name в первой строке или заполнит ячейки Page_Name в следующей строке (или rowS) - значения ячеек в столбце # и столбце shrt в редактируемых строках получат значения программно по этому коду части:

$DataGridView1.Add_CellValueChanged({autofill})
Function autofill{

$Numbr = $DataGridView1.CurrentRow.Index+1
$DataGridView1.CurrentRow.Cells[0].value = $Numbr

$Name_Page = $DataGridView1.CurrentRow.Cells[1].value
$preshrt = $Name_Page.ToString($Value) -ireplace "[aoueyi]" 
$preshrt = $preshrt.ToUpper()
$shrt = $preshrt[0]+$preshrt[1]+$preshrt[2]
$DataGridView1.CurrentRow.Cells[2].value = $shrt
}

Моей основной целью является получение значений всех ячеек в столбце Page_Name в виде переменной (или массива).
Итак, я попытался добавить следующую строку к функции выше.

$Pages = $Row.Page_Name+$DataGridView1.CurrentRow.Cells[1].value

Но ничего не возвращает... (либо $Row.Page_Name)

Я могу получить значения всех ячеек во всех строках с помощью

$Page_NamesListRows = @($DataGridView1.Rows.Cells.Value)

(К сожалению) он возвращает переменную, состоящую из всех существующих ячеек, а не массива строк.
Но когда я пытаюсь

$Page_Names = $DataGridView1.Rows.Cells[1].Value

or

$Page_Names = $DataGridView1.Columns[1].Cells.Value

чтобы получить только имена страниц, он возвращает ошибку, не может получить значение нулевого массива (либо в случае с @(...) для правой части)

Может ли кто-нибудь ответить... есть какой-либо способ получить значения всех существующих ячеек в столбце Page_Name.
Честно говоря, не имеет значения, будут ли DGVData автоматически редактироваться путем изменения события значения ячеек или нет.

Мне нужно получить только значения столбца Page_Name.

В конце я хочу извиниться за мой английский язык. Имеет довольно низкий уровень. И заранее спасибо модератору за исправление моих ошибок.


person Владимир Константинов    schedule 22.06.2020    source источник


Ответы (1)


Боюсь, вам придется получить массив значений, перебирая строки в столбце Page_Name.
Последняя строка в DataGridView всегда будет новой строкой, которую создает пользователь, поэтому вам нужно пропустить Вон тот.

Либо сделав это:

# -1 to skip the always present empty row at the bottom
$Page_Names = for($row = 0; $row -lt $DataGridView1.Rows.Count - 1; $row++) {
    $DataGridView1.Rows[$row].Cells.Item("Page_Name").Value
}

Или что-то вроде:

$Page_Names = $DataGridView1.Rows | ForEach-Object {
    $data = $_.Cells.Item("Page_Name").Value
    if ($data) { $data }
}

Or:

$Page_Names = foreach ($row in $DataGridView1.Rows) {
    $row.Cells.Item("Page_Name").Value
}
$Page_Names = $Page_Names[0..($Page_Names.Count - 2)]

Последний вариант требует больших затрат, поскольку при удалении последнего элемента необходимо воссоздать весь массив

P.S.1 Не забудьте вызвать методы Dispose() как для объекта $DataGridview1, так и для основной формы, когда закончите с графическим интерфейсом

P.S.2 Я не вижу свойства с именем AllowUserToAddRowsChanged в DataGridView..


ИЗМЕНИТЬ

Надеюсь, чтобы лучше показать, что я имею в виду, вот демонстрационная форма с элементом управления DataGridView.

Исходные данные берутся из фиктивного CSV-файла с этим внутри:

"1";"Page number 1";"PN1"
"2";"Page number 2";"PN2"
"3";"Page number 3";"PN3"
"4";"Page number 4";"PN4"
"5";"Page number 5";"PN5"
$form            = New-Object System.Windows.Forms.Form
$form.ClientSize = New-Object Drawing.Size 580, 505
$form.text       = "20/4/2020 v. 0.1 All Right reserved (c) "
$form.TopMost    = $true

$DataGridView1                    = New-Object system.Windows.Forms.DataGridView
$DataGridView1.Location           = New-Object System.Drawing.Point 20,25
$DataGridView1.Width              = 363
$DataGridView1.Height             = 150
$DataGridView1.AllowUserToAddRows = $true
$DataGridView1.Name               = "Page-List"
$DataGridView1.ColumnCount        = 3
$DataGridView1.Columns[0].Name    = '#'
$DataGridView1.Columns[0].Width   = "40"
$DataGridView1.Columns[1].Name    = 'Page_Name'
$DataGridView1.Columns[1].Width   = "205"
$DataGridView1.Columns[2].Name    = "shrt"
$DataGridView1.Columns[2].Width   = "75"
$DataGridView1.AllowUserToAddRows = $true
$DataGridView1.ReadOnly           = $false

# Populate the DGV with the data from the CSV
$CsvData = Import-Csv -Path 'D:\Test\TEMPLATE_ROW.csv' -Delimiter ";" -Header "#", "Page_Name", "shrt"
foreach ($row in $CsvData) {
    [void]$DataGridView1.Rows.Add($row.'#', $row.Page_Name, $row.shrt)
}

# add the DGV to the form
$form.Controls.Add($DataGridView1)

# show the form and capture the result so you can check if the user cancelled or pressed OK
$result = $form.ShowDialog()

# at this point, you can read the data from the DataGridView column of interest
$Page_Names = for($row = 0; $row -lt $DataGridView1.Rows.Count - 1; $row++) {
    $DataGridView1.Rows[$row].Cells.Item("Page_Name").Value
}

# cleanup memory by destroying the DGV and the from
$DataGridView1.Dispose()
$form.Dispose()

Теперь в переменной $Page_Names у вас будут данные из столбца Page_Name в элементе управления DataGridView.

# show on screen
$Page_Names
person Theo    schedule 22.06.2020
comment
Большое спасибо за ответ! Теперь я полностью запутался. И я думаю, что проблема в моем коде, потому что все эти 3 параметра возвращают только значение первой строки Page_Name.... Ни одна из строк, отредактированных вручную, не стала частью $DataGridView1.Rows.... Так что это основная проблема для меня ... как объект $DataGridview1, так и основная форма - оба? у меня только 1$DGV. И я думаю, что на самом деле не знаю, что такое основная форма... о, я пытался установить AllowUserToAddRows, но это оказалось бесполезным... - person Владимир Константинов; 23.06.2020
comment
@ВладимирКонстантинов Ну .. объект DataGridView добавляется к элементам управления вашей (основной) формы. Когда закончите, вы должны очистить память, выполнив $form.Dispose(), а также `$DataGridView1.Dispose(). I have no idea what you called your form, so you need to use that variable name. AllowUserToAddRows` в порядке, но AllowUserToAddRowsChange не является допустимым свойством, если вы оставите эту строку, вы увидите сообщение об ошибке. - person Theo; 23.06.2020
comment
Мой английский довольно плохой. И я часто ошибаюсь. Извините за это... Я думал, что DGV - это основная форма для отображения данных. Если я правильно понял, я должен использовать 2 DGV? 1 для отображения экспортированных данных из csv и второго для добавления вручную? Если вам интересно, есть полный файл кода drive.google.com/file /d/1S5jvk6YyWccRkjW1VYxMDQ_rhxzOXtuf/. Я был бы более чем счастлив ПОЛНОСТЬЮ, если бы вы мне помогли. Я честно пытаюсь найти на docs.ms подробную инструкцию для объекта/управления DGV. Но все руководства написаны на c# и .net. Мне он кажется китайским... - person Владимир Константинов; 23.06.2020
comment
@ВладимирКонстантинов Вам не нужно беспокоиться о своем английском, потому что он в порядке. Я отредактировал свой ответ и вставил демо-код, чтобы показать, что я имею в виду. Конечно, здесь нет причудливых кнопок и прочего, что есть в вашем коде, но для демонстрации этого должно хватить. Я надеюсь, что это объясняет некоторые вещи для вас. - person Theo; 23.06.2020
comment
О)) Вы умничка!)) Большое вам спасибо!!Сейчас начинаю учиться)) PS:Большая часть причудливых вещей в моем коде появилась только потому, что мне нужно было что-то делать(независимо от того, что бы это ни быть) работает после нескольких часов безуспешных попыток сделать полезный рабочий код, который мне действительно нужен... - person Владимир Константинов; 23.06.2020
comment
Я внимательно изучил эту демонстрацию и хочу поблагодарить вас за потраченное время!!!!)))) Но в моем случае есть небольшая разница.... После того, как DGV отображает содержимое csv-файла (на самом деле 1 строка). Я (или другой пользователь) вручную добавляю следующие строки по редактированию ячеек новой строки. Конечно, что бы я ни делал, вручную добавлял строки, не становящиеся частью RowCollection. Таким образом, все манипуляции с переменными DGV-элементов действуют только для тех строк, которые были преобразованы из содержимого csv. Я даже пытаюсь экспортировать @($DataGridView1.Rows.Cells.Value) после ручного добавления строк в тот же CSV, из которого 1 строка была экспортирована в - person Владимир Константинов; 24.06.2020
comment
обновить коллекцию строк. Кажется, что это не имеет никакого смысла. Csv стал пустым после этих манипуляций. Я начал изучать документацию для ограниченного исходного кода для DGV. Но во всех примерах, которые я создал для источника данных с использованием sql. Я действительно думаю, что источник базы данных tsql для макс. 5 имен веб-страниц - не очень хорошая идея... - person Владимир Константинов; 24.06.2020