Связать WPF XAML с DataGrid в PowerShell - PullRequest
0 голосов
/ 19 сентября 2018

Я следовал вместе с руководством, расположенным здесь , пытаясь создать графический интерфейс с PowerShell, и все идет хорошо, за исключением того, что у меня есть DataGrid, который должен быть заполнен в моем GUI.

В моей сетке XML у меня есть:

[xml]$form=@"
<Window
    [...]
    <Grid>
        [...]
        <DataGrid Name="CSVGrid" HorizontalAlignment="Left" Height="340" Margin="10,60,0,0" VerticalAlignment="Top" Width="765"/>
        [...]
    </Grid>
</Window>
"@

Теперь в учебном пособии для создания формы используется следующее:

$XMLReader = (New-Object System.Xml.XmlNodeReader $Form)
$XMLForm = [Windows.Markup.XamlReader]::Load($XMLReader)

Но чтобы заставить работать мою DataGrid, я считаю, чтомне нужно определить мой "CSVGrid" DataGrid как " system.Windows.Forms.DataGridView " где-нибудь, но я не уверен, как связать это вместе.Запуск его без определения этого приведет к появлению ошибок, если я попытаюсь вызвать какие-либо свойства DataGrid, такие как установка количества столбцов или имен столбцов.

Любые идеи?

Способ POSHGUI реализует их формы на самом деле отлично работает для моих целей, но я предпочитаю редактировать формы WPF в Visual Studio.При необходимости я могу перестроить форму в POSHGUI, но, надеюсь, есть способ связать это вместе здесь, чтобы я мог продолжать использовать VS GUI для редактирования GUI формы.

Edit: Следует отметить, что в форме не только сетка данных, на случай, если она не ясна.

Редактировать 2: В качестве дополнительного бита информации, способ, которым POSHGUI форматирует элементы управлениявыглядит так:

#the form itself
$Form                            = New-Object system.Windows.Forms.Form
$Form.ClientSize                 = '400,400'
$Form.text                       = "Form"
$Form.TopMost                    = $false
#a datagrid
$DataGridView1                   = New-Object system.Windows.Forms.DataGridView
$DataGridView1.width             = 382
$DataGridView1.height            = 335
$DataGridView1.location          = New-Object System.Drawing.Point(8,55)
#a button
$Button1                         = New-Object system.Windows.Forms.Button
$Button1.text                    = "My button"
$Button1.width                   = 126
$Button1.height                  = 30
$Button1.location                = New-Object System.Drawing.Point(156,13)
$Button1.Font                    = 'Microsoft Sans Serif,10'

Затем он связывает их вместе с:

$Form.controls.AddRange(@($DataGridView1,$Button1))

Так что счастливо определяет переменную DataGrid как "system.Windows.Forms.DataGridView", & c,тогда как метод помещения всего XML в переменную $ и передачи его в «System.Xml.XmlNodeReader» не делает различий, в которые я не верю, поэтому я не могу вызвать какие-либо свойства DataGrid.

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

Редактировать 3: Если это вообще поможет, проверьте раскрывающийся список intellisense,Существуют различные свойства DataGrid, но не ColumnCount для exдостаточно:

enter image description here

Так, может быть, это работает как задумано?Но в то же время, если моя переменная DataGrid определена явно как system.Windows.Forms.DataGridView, как в примере с POSHGUI, то настройка ColumnCount работает безупречно ...

Ответы [ 2 ]

0 голосов
/ 15 мая 2019

Я немного ее изменил:

  • - это функция (допускает несколько окон)
  • возвращает массив элементов
  • загружает структуру представления (поддерживает x: Bind as Binding)
  • вы можете создать любую форму WPF в Visual Studio и загрузить ее (в основном, не забудьте о каких-либо дополнительных классах, которые были определены в XAML, и, возможно, загрузите их тип в шикарном)

Более продвинутая версия: поддержка обработчика кликов

function LoadXamlForm
{

    Param
    (
        [Parameter(Mandatory=$true)] $xamlFile
    )

    Add-Type -AssemblyName PresentationFramework

    $inputXML = Get-Content -Path $xamlFile


    # https://stackoverflow.com/a/52416973/1644202

    $inputXML = $inputXML -replace 'mc:Ignorable="d"','' -replace "x:N",'N' -replace '^<Win.*', '<Window' -replace "x:Bind", "Binding"
    [void][System.Reflection.Assembly]::LoadWithPartialName('presentationframework')
    [xml]$XAML = $inputXML
    #Read XAML

        $reader=(New-Object System.Xml.XmlNodeReader $XAML) 
    try{$Form=[Windows.Markup.XamlReader]::Load( $reader )}
    catch [System.Management.Automation.MethodInvocationException] {
        Write-Warning "We ran into a problem with the XAML code.  Check the syntax for this control..."
        write-host $error[0].Exception.Message -ForegroundColor Red
        if ($error[0].Exception.Message -like "*button*"){
            write-warning "Ensure your &lt;button in the `$inputXML does NOT have a Click=ButtonClick property.  PS can't handle this`n`n`n`n"}
    }
    catch{#if it broke some other way <span class="wp-smiley wp-emoji wp-emoji-bigsmile" title=":D">:D</span>
        Write-Host "Unable to load Windows.Markup.XamlReader. Double-check syntax and ensure .net is installed."
            }

    #===========================================================================
    # Store Form Objects In PowerShell
    #===========================================================================
    $Elements = @{}
    $xaml.SelectNodes("//*[@Name]") | %{ $Elements[$_.Name] = $Form.FindName($_.Name) }

    return $Form, $Elements
}


$Form,$Elements = LoadXamlForm .\gui.xaml

$Elements.lvApps.AddChild([pscustomobject]@{Name='Ben';Description="sdsd 343"})

$Form.ShowDialog() | out-null

просто любой xaml - я знаю, что это не сетка данных - но тем не менее дает вам пример использования

<Window x:Class="WpfApp.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:WpfApp2"
    mc:Ignorable="d"
    Title="MainWindow" Height="450" Width="800">
    <Grid>
        <ListView SelectionMode="Multiple" x:Name="lvApps" Height="371" VerticalAlignment="Top">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal" Height="64" AutomationProperties.Name="{Binding Name}">
                        <Ellipse Height="48" Width="48" VerticalAlignment="Center">
                            <Ellipse.Fill>
                                <ImageBrush ImageSource="{Binding ButtonImage}"/>
                            </Ellipse.Fill>
                        </Ellipse>
                        <StackPanel Orientation="Vertical" VerticalAlignment="Center" Margin="12,0,0,0">
                            <TextBlock Text="{Binding Name}" />
                            <TextBlock Text="{Binding Description}" />
                        </StackPanel>
                    </StackPanel>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </Grid>
</Window>
0 голосов
/ 20 сентября 2018

Прежде чем мы углубимся в это, вы не можете использовать DataGridView в WPF (это то, что я покажу вам здесь).Вы можете , однако, вместо этого используйте DataGrid , что в значительной степени одно и то же (и намного короче и проще в PowerShell, чем Windows Forms, что и использует POSHGUI (удивительный инструмент, хотя иis).

Если вам все еще интересно, вот супер базовый обзор того, как вы могли бы это сделать. Сначала определим XAML

$inputXML = @"
<Window x:Class="WpfApp2.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:WpfApp2"
    mc:Ignorable="d"
    Title="MainWindow" Height="450" Width="800">
<Grid>
    <DataGrid Name="Datagrid" AutoGenerateColumns="True" >
        <DataGrid.Columns>
            <DataGridTextColumn Header="Name" Binding="{Binding Name}" Width="180" />
            <DataGridTextColumn Header="Type" Binding="{Binding Type}" Width="233"/>
        </DataGrid.Columns>
    </DataGrid>
</Grid>
</Window>
"@ 

Обратите внимание, что мы определяем, какиестолбцы из нашего входного объекта мы хотим отобразить. Пока еще не нашли отличный способ их автоматического создания.

Затем загрузите форму (используя метод из моего пошагового руководства по теме здесь )

$inputXML = $inputXML -replace 'mc:Ignorable="d"','' -replace "x:N",'N' -replace '^<Win.*', '<Window'
[void][System.Reflection.Assembly]::LoadWithPartialName('presentationframework')
[xml]$XAML = $inputXML
#Read XAML

    $reader=(New-Object System.Xml.XmlNodeReader $xaml) 
try{$Form=[Windows.Markup.XamlReader]::Load( $reader )}
catch [System.Management.Automation.MethodInvocationException] {
    Write-Warning "We ran into a problem with the XAML code.  Check the syntax for this control..."
    write-host $error[0].Exception.Message -ForegroundColor Red
    if ($error[0].Exception.Message -like "*button*"){
        write-warning "Ensure your &lt;button in the `$inputXML does NOT have a Click=ButtonClick property.  PS can't handle this`n`n`n`n"}
}
catch{#if it broke some other way <span class="wp-smiley wp-emoji wp-emoji-bigsmile" title=":D">:D</span>
    Write-Host "Unable to load Windows.Markup.XamlReader. Double-check syntax and ensure .net is installed."
        }

#===========================================================================
# Store Form Objects In PowerShell
#===========================================================================

$xaml.SelectNodes("//*[@Name]") | %{Set-Variable -Name "WPF$($_.Name)" -Value $Form.FindName($_.Name)}

Теперь, чтобы добавить некоторые элементы в этот DataGridView. Приведенный выше код также дает нам переменную под названием $WPFGridView в нашем сеансе. Мы можем добавить дочерние элементы в наш DataGridView, вызвав .AddChild()метод этой переменной и добавление к ней элементов, которые имеют по крайней мере те же свойства, которые мы определили в нашем DataGrid ранее.

$WPFDatagrid.AddChild([pscustomobject]@{Name='Stephen';Type=123})
$WPFDatagrid.AddChild([pscustomobject]@{Name='Geralt';Type=234})

Затем, чтобы отобразить наш графический интерфейс, мы вызываем $Form 's ShowDialog() метод вроде так, и тогда нижняя должна нас приветствовать.

$Form.ShowDialog()

The image depicts a Windows 10 operating system displaying a Windows Presentation Foundation User Interface which contains a datagrid with two columns that contain the items added in the code snippet above

Полный пример кода доступен здесь .Если вы хотите больше узнать об использовании WPF GUI-элементов, подобных этому, у меня есть полное пошаговое руководство, доступное здесь .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...