Рациональным подходом к созданию GUI в Powershell будет случай когда декларативное описание графического интерфейса отделяется от остального кода исполнения. Такой подход обеспечивает технология Windows Presentation Foundation (WPF).
При использовании WPF графический интерфейс описывается с помощью базирующегося на XML языка разметки XAML (Extensible Application Markup Language). Таким образом, дизайн интерфейса отделяется от логики сценария, работающего с этим интерфейсом. Для работы с объектами WPF в PowerShell нужно загрузить сборку PresentationFramework:
PS C: \Users\xenial> Add-Type -AssemblyName PresentationFramework
Создадим сначала простейшее диалоговое окно без элементов размером 300x200 пикселов и с заголовком "Форма WPF". На первом шаге с помощью here-string создадим строку $xaml с XML-разметкой, содержащей один тег <window/> с атрибутами Width, Height и Title, и преобразуем эту строку в объект XML:
PS С:\Users\xenial> [xml]$xaml = @"
<Window
xmlns="http: //schemas.microsoft.com/winfx/2006/xaml/presentation”
xmlns :x="http: //schemas.microsoft.com/winfx/2006/xaml"
x:Name="Window" Тitle="Form WPF” Height=”200" Width=”300”
/>
"@
Атрибут xmlns здесь определяет пространство имен, содержащее имена элементов и атрибутов, которые можно использовать в разметке Windows Presentation Foundation. Префикс х перед атрибутом указывает на то, что данный атрибут относится к данному пространству имен. Создадим теперь экземпляр класса XmlNodeReader, передав ему объект $xami в качестве аргумента. Полученный объект сохраним в переменной $ reader:
PS С:\Users\xenial> $reader = (New-Object System.Xml.XmlNodeReader $xaml)
Объект, соответствующий диалоговому окну, создается с помощью статического метода Load () класса XamlReader. В этот метод передается объект $ reader:
PS С:\Usегs\ xenial> $window = [Windows.Markup.XamlReader] : : Load($reader)
Теперь окно можно отобразить на экране с помощью метода showDiaiog:
PS С:\Users\xenial> $window.ShowDialog()
При этом работа оболочки PowerShell приостановится, для ввода следующей команды нужно закрыть наше диалоговое окно. Добавим в нашу форму элемент <Grid>, задающий сетку для размещения других элементов управления.
PS С:\Users\xenial> [xml]$xaml = @"
<Window
xmlns="http: //schemas .micro soft. ccm/winfx/2006/xaml/presentation"
xmlns: x="http: //schemas.microsoft. com/winfx/2006/xaml"
x :Name=" Window" Title="Form WPF" Height="200" Width="300"
<Grid x:Name="Grid">
<Gr id.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
</Grid>
</Window>
"@
Сетка не отображается на экране, поэтому внешний вид главной формы (диалогового окна) не изменится, форма останется пустой. Поместим теперь на форму надпись (тег <Label> С именем Message) и кнопку (тег <Button> с именем changeMessage). Надписи в этих элементах задаются с помощью атрибута content, расположение элемента в ячейке сетки определяется с помощью атрибутов Grid.Column И Grid.Row.
PS C: \Users\xenial> [xml]$xaml = @"
<Window
xmlns="http: //schemas .microsoft. com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas .microsoft .com/ winf x/2006/xaml"
x:Name="Window” Title="Form WPF" Height=”200” Width="300”
>
<Grid x:Name="Grid">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Label x:Name= "Message"
Content="Hello!"
Grid.Column=”0"
Grid.Row="0"
/>
<Button x:Name= " ChangeMessage"
Content="Press!"
Grid.Column="1"
Grid.Row="1"
/>
</Grid>
</Window>
"@
Отобразим форму:
С: \Users\xenial> $reader = (New-Object System.Xml. XmlNodeReader $xaml)
PS C:\Users\xenial> $window = [Windows.Markup.XamlReader] ::Load($reader)
PS C:\Users\xenial> $window.ShowDiaiog()
С помощью команды Set-Content поместим XAML-разметку для нашей формы в файл wpf test.xaml, в коде выше добавим в конец строку:
...
"@ | Set-Content -Path ./mywpf.xaml -Encoding UTF8
Теперь для отображения формы мы можем прочитать ее разметку из файла:
PS С:\Users\xenial> [xml]$xaml = Get-Content -Path ./mywpf.xaml -Encoding UTF8
PS C:\Users\xenial> $reader = (New-Object System.Xml.XmlNodeReader $xaml)
PS C:\Users\xenial> $window = [Windows.Markup.XamlReader] ::Load($reader)
Осталось добавить форме функциональность, создав обработчики нужных событий, возникающих на элементах управления. Это делается практически так же, как и при использовании WinForms, за исключением того, что нам нужно предварительно создать объекты-переменные, соответствующие элементам управления загруженной формы.
Напомним, что для тегов элементов управления мы задавали атрибут Name из пространства имен XAML-разметки для WPF:
<Label x:Name="Message"
...
/>
<Button х:Name="ChangeMessage"
...
/>
По значению атрибута Name с помощью метода $ window. FindName о получим ссылки на соответствующие элементы управления:
PS С: \Users\xenial> $messageLabel = $ window. FindName ("Mеssage")
PS C: \Users\xenial> $changeButton = $ window. FindName ("ChangeMessage”)
Пусть, как и в примере с WinForms, при нажатии кнопки текст надписи в нашей форме должен измениться на ’’Buy-buy?”. Для этого зададим обработчик события Click на кнопке с помощью метода Add_click:
PS C:\Users\xenial> $changeButton. Add_Click ({$messageLabel. Content= ’ Buy-buy? ’ })
Теперь форму можно отобразить на экране и проверить результат нажатия кнопки
PS С:\Users\xenial> $window.ShowDialog()
Таким образом, при работе с WPF мы можем создавать и изменять дизайн интерфейса независимо от его функционала. Кроме того, XAML-описание формы не зависит от специфики PowerShell, как это было в случае интерфейса на базе WinForms, поэтому вариантов выбора визуального конструктора для построения форм становится больше. Кроме платных специализированных сред разработки сценариев PowerShell (Sapien PowerShell Studio, PowerShell GUI Designer) можно воспользоваться бесплатной платформой Microsoft Visual Studio Community Edition. Также у вас есть шанс что в этом случае ваше GUI-приложение будет работать на серверах Windows Core с включенным минимальным графическим интерфейсом.
Удачи.
Слава Украине!
No comments:
Post a Comment
А что вы думаете по этому поводу?