posts - 104 , comments - 115 , trackbacks - 0

My Links

News

Disclaimer: Right here... Github: Code all the things! PS GUI Series: < Coming Soon! > PS Scripts: < Coming Soon! >

Tag Cloud

Article Categories

Archives

Post Categories

Image Galleries

Blogs

Forums

Lync

Storage

Tools

Virtualization

Web comics

[Powershell Series] Creating Graphical User Interfaces – The basics

This blog has move to: http://hornedowl.net/

So, you've been writing PowerShell Scripts that interact with users and figured
"Hey, I really don't want to listen to the complaints that this it is archaic to use
a menu structure in the console" anymore, or perhaps you just want to learn something new .

This article aims to give you the basics to create a simple Windows Presentation Framework
form (using XAML) and presenting it to your user.

First things first… What is XAML?

XAML stands for eXtensible Application Markup Language, and it's Microsoft's variant of XML
for describing a Graphical User Interface. Previously you would use something like WinForm (shudder),
which would create the GUI in the same language that you would use to interact with the GUI.
WinForms doesn't scale well and is (in my opinion) horrible to work with.

The Editor of choice

There's quite a few editors you can use to create to make XAML windows (notepad being the most basic
one if you're feeling adventurous… ), but I prefer Visual Studio for my work. It helps that it comes with
my MSDN subscription, but there are other fine editors out there if you would choose to use a different
one. If you do decide to use Visual Studio, I highly recommend the PowerShell plug-in:
https://marketplace.visualstudio.com/items?itemName=AdamRDriscoll.PowerShellToolsforVisualStudio2017-18561

The good stuff

Your first window!

Yup, I use a Dark Theme … So what we see here is a number of different elements:

  1. The window
  2. The grid
  3. A label
  4. A textbox
  5. A button
  6. An image

Easy so far right? But how to we create these in XAML? By using the following XAML code:

<Window

 

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

Title="MainWindow"

Height="204.683"

Width="525">

 

<!-- Grid area -->

<Grid>

<!-- A Label -->

<Label Content="Label" HorizontalAlignment="Left" Margin="68,38,0,0" VerticalAlignment="Top" Width="197"/>

<!-- A Button -->

<Button Content="Button" HorizontalAlignment="Left" Margin="307,41,0,0" VerticalAlignment="Top" Width="75"/>

<!-- A Textbox -->

<TextBox HorizontalAlignment="Left" Height="23" Margin="127,41,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="120"/>

<!-- An Image -->

<Image HorizontalAlignment="Left" Margin="198,106,0,10" Width="58" Source="C:\Users\Marc\Downloads\Cylon_Head.png" />

</Grid>

</Window>

Great! But what the hell does all of it mean?

<Window> </Window>

This is where it all starts. It allows users to interact with the application, and try to break it. The window tag
consists of a client, and non-client area. The non-client area is implemented by WPF and includes the part of
a window that are common to most windows: A border, title bar, icon, Minimize, Maximize, restore, close
buttons, and of course a system menu

The client area is where app specific content is added. Meaning, that's the area number 2 and above in the
picture from earlier live.

Properties

A full list of all the properties can be found here:
https://docs.microsoft.com/en-us/dotnet/api/system.windows.window?view=netframework-4.7.2

Typically, there's a few you would use to customize the window most commonly:

  • Title: This property will define the main name of your GUI
  • Height: Surprisingly, this defines the height of the GUI
  • Width: Defines the width of the GUI
  • Background: Defines the color of the client area
  • Borderbrush: The color your border should have
  • BorderThickness: How large your border should get
  • FontFamily: Sets the font for the client area
  • FontSize: Sets the size of the fonts in the client area

For example, changing the XAML code from early to this:

<Window

 

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

Title="Just a demo"

Height="204.683"

Width="525"

Background="Red"

BorderBrush="Blue"

BorderThickness="4"

FontFamily="Algerian"

FontSize="24"

>

 

<!-- Grid area -->

<Grid>

<!-- A Label -->

<Label Content="Label" HorizontalAlignment="Left" Margin="21,31,0,0" VerticalAlignment="Top" Width="197"/>

<!-- A Button -->

<Button Content="Button" HorizontalAlignment="Left" Margin="307,41,0,0" VerticalAlignment="Top" Width="127"/>

<!-- A Textbox -->

<TextBox HorizontalAlignment="Left" Height="32" Margin="127,41,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="120"/>

<!-- An Textbox -->

<Image HorizontalAlignment="Left" Margin="198,106,0,10" Width="58" Source="C:\Users\Marc\Downloads\Cylon_Head.png"/>

</Grid>

</Window>

Would result in this:

All this building is fun and games, but how do we actually use it?

Actually calling it all from Powershell is quite simple. Generally you'll see 2 different approaches on this. One would be to define the XAML code in your PowerShell script as such:

[XML]$xaml=@"

<Window

 

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

Title="Just a demo"

Height="204.683"

Width="525"

Background="Red"

BorderBrush="Blue"

BorderThickness="4"

FontFamily="Algerian"

FontSize="24"

>

 

<!-- Grid area -->

<Grid>

<!-- A Label -->

<Label Content="Label" HorizontalAlignment="Left" Margin="21,31,0,0" VerticalAlignment="Top" Width="197"/>

<!-- A Button -->

<Button Content="Button" HorizontalAlignment="Left" Margin="307,41,0,0" VerticalAlignment="Top" Width="127"/>

<!-- A Textbox -->

<TextBox HorizontalAlignment="Left" Height="32" Margin="127,41,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="120"/>

<!-- An Textbox -->

<Image HorizontalAlignment="Left" Margin="198,106,0,10" Width="58" Source="C:\Users\Marc\Downloads\Cylon_Head.png"/>

</Grid>

</Window>

"@

 

Other like keeping the xaml code in a separate xaml file and import it:

[xml]$xaml = Get-Content -Path "$($VariableHash.FormsDir)\MainWindow.xaml"

 

Personally, that last one is the one I prefer. Full code to show your gui:

# Loading required assemblies    

Add-Type –assemblyName PresentationFramework # Required to show the GUI

 

# Loading XAML code    

[xml]$xaml = Get-Content -Path "<Path to XAML file>"

 

    # Adding proper namespace

    $manager = New-Object System.Xml.XmlNamespaceManager -ArgumentList $xaml.NameTable

$manager.AddNamespace("x", "http://schemas.microsoft.com/winfx/2006/xaml");

        

# Loading in to XML Node reader

$Reader= New-Object System.Xml.XmlNodeReader $xaml

        

# Loading XML Node reader in to $SyncHash window property to launch later

$window = [Windows.Markup.XamlReader]::Load($reader)

 

# Show the window!

$window.ShowDialog()

Just one more thing…

Right now, you won't be able to do much with the above code. There are no names defined, nor event actions… So for each element that we want to interact with we should add a Name property:

<Window

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

x:Name="MainWindow"

Title="Just a demo"

Height="204.683"

Width="525"

Background="Red"

BorderBrush="Blue"

BorderThickness="4"

FontFamily="Algerian"

FontSize="24"

>

 

<!-- Grid area -->

<Grid>

<!-- A Label -->

<Label x:Name="lblLabel" Content="Label" HorizontalAlignment="Left" Margin="21,31,0,0" VerticalAlignment="Top" Width="197"/>

<!-- A Button -->

<Button x:Name="btnButton" Content="Button" HorizontalAlignment="Left" Margin="307,41,0,0" VerticalAlignment="Top" Width="127"/>

<!-- A Textbox -->

<TextBox x:Name="txtTextBox" HorizontalAlignment="Left" Height="32" Margin="127,41,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="120"/>

<!-- An Textbox -->

<Image x:Name="imgImage" HorizontalAlignment="Left" Margin="198,106,0,10" Width="58" Source="C:\Users\Marc\Downloads\Cylon_Head.png"/>

</Grid>

</Window>

Now that you have them named, you can connect the controls to variables (otherwise you cannot use them…):

#region connecting controls

$MainWindow = $Window.FindName("MainWindow")

$label = $Window.FindName("lblLabel")

$TextBox = $Window.FindName("txtTextBox")

$Button = $Window.FindName("btnButton")

$Image = $Window.FindName("imgImage")

#endregion connecting controls

For a button click, use the following:

#region Event Handling

    $Button.Add_Click({

        # Do something

    })

#endregion Event Handling

Which would make the full code:

 

# Loading required assemblies    

Add-Type –assemblyName PresentationFramework # Required to show the GUI

 

# Loading XAML code    

[xml]$xaml = Get-Content -Path "$PSScriptRoot\WpfWindow1.xaml"

 

    # Adding proper namespace

    $manager = New-Object System.Xml.XmlNamespaceManager -ArgumentList $xaml.NameTable

$manager.AddNamespace("x", "http://schemas.microsoft.com/winfx/2006/xaml");

        

# Loading in to XML Node reader

$Reader= New-Object System.Xml.XmlNodeReader $xaml

        

# Loading XML Node reader in to $SyncHash window property to launch later

$window = [Windows.Markup.XamlReader]::Load($reader)

 

#region connecting controls

$MainWindow = $Window.FindName("MainWindow")

$label = $Window.FindName("lblLabel")

$TextBox = $Window.FindName("txtTextBox")

$Button = $Window.FindName("btnButton")

$Image = $Window.FindName("imgImage")

#endregion connecting controls

 

#region Event Handling

    $Button.Add_Click({

        # Do something

    })

#endregion Event Handling

 

# Show the window!

$window.ShowDialog()

 

That's all folks!

And with that comes the end of this post in the series on Creating Graphical User Interfaces. I hope you enjoyed yourself, learned something new, or gained a greater understanding of our topic.
Until next time!

https://www.youtube.com/watch?v=gBzJGckMYO4

This blog has move to: http://hornedowl.net/

Print | posted on Tuesday, February 19, 2019 9:59 AM | Filed Under [ Powershell #GUIBuilding #XAML ]

Feedback

No comments posted yet.
Post A Comment
Title:
Name:
Email:
Comment:
Verification:
 

Powered by: