top of page
avicoren

First Window to the (hello) world

Updated: Dec 27, 2021

Let's get down to business.


Our prerequisite is that you'll have your project's skeleton ready.

In case you've missed it, check out my post on that.


So, let's populate the ps1 and xaml files:


Open your text editor and paste this code to a newly created file, then save it as Example1.xaml inside your project's root folder.

You can also download both files from my GitHub (both Example1 files).

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:mmaterialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
    Name="MainWindow"
    Title="Examples"
    Height="500"
    Width="500"
    Style="{DynamicResource MaterialDesignWindow}" 
    WindowStartupLocation="CenterScreen"
    ResizeMode="CanResize"
    TextElement.Foreground="{DynamicResource MaterialDesignBody}"
    TextElement.FontSize="14"
    TextElement.FontFamily="Roboto"
    TextOptions.TextFormattingMode="Ideal"
    TextOptions.TextRenderingMode="Auto"
    Background="{DynamicResource MaterialDesignPaper}" >

    <Window.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Light.xaml" />
                <ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Defaults.xaml" />
                <ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/Recommended/Primary/MaterialDesignColor.BlueGrey.xaml" />
                <ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/Recommended/Accent/MaterialDesignColor.DeepOrange.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Window.Resources>

    <Grid>
        <StackPanel VerticalAlignment="Center">
            <TextBox Name="TxtBox1" Width="200" />
            <Button  Name="Btn1"    Width="100" Content="Click Me"  Margin="0,30,0,0" />
            <TextBox Name="TxtBox2" Width="200" Foreground="Green"  Margin="0,10,0,0" />                            
        </StackPanel>
    </Grid>

</Window>

Next, do the same for this code and save it as Example1.ps1

###########
#  Learn how to build Material Design based PowerShell apps
#  --------------------
#  Example1: Hello World
#  --------------------
#  Avi Coren (c)
#  Blog     - https://avicoren.wixsite.com/powershell
#  Github   - https://github.com/DrHalfBaked/PowerShell
#  LinkedIn - https://www.linkedin.com/in/avi-coren-6647b2105/
#
[Void][System.Reflection.Assembly]::LoadWithPartialName('presentationframework')
[Void][System.Reflection.Assembly]::LoadFrom("$PSScriptRoot\Assembly\MaterialDesignThemes.Wpf.dll")
[Void][System.Reflection.Assembly]::LoadFrom("$PSScriptRoot\Assembly\MaterialDesignColors.dll")

try {
    [xml]$Xaml = (Get-content "$PSScriptRoot\Example1.xaml")
    $Reader = New-Object System.Xml.XmlNodeReader $Xaml
    $Window = [Windows.Markup.XamlReader]::Load($Reader)
} 
catch {
    Write-Error "Error building Xaml data.`n$_"
    exit
}

$Xaml.SelectNodes("//*[@Name]") | ForEach-Object { Set-Variable -Name ($_.Name) -Value $Window.FindName($_.Name) -Scope Script }

$Btn1.Add_Click({$TxtBox2.Text = $TxtBox1.Text})

$Window.ShowDialog() | out-null

Now open any PowerShell console, navigate to your project's folder and run the Example1.ps1 script. Congratz! your first Material Design script is alive.

You should see this window:




Before we talk about the code, take a look at the window. The controls you see are Material Design ones and they are responding to your actions like mouse clicking/hovering with animation and transition. Also, for you guys who moved from windows.forms and it's their first WPF experience - play with the window's size and see how it responds and reorganize all the controls accordingly.

As for the program itself, just write "Hello World" on the top textbox and click the button. It will populate the bottom textbox with green text. Nice!


Let's review the Xaml file. Although the code format on this post it too narrow and it breaks the lines we will overcome this obstacle. You can look at your own file which should look nicer in your editor. If you know Xaml you can skip it.

So Xaml is built like an xml file which is an organized tree of elements in a parent-child system. each element have attributes and contains data.

Every element is defined in a tag and it got to have it's twin closing tag.

Our root element is <Window> and all the content is its children. At the end comes its closing tag </Window> (closing tag has a forward slash followed by the same name of the opening tag).

You can see that it's not really a simple <Window> tag. It has a lot of properties like size, title etc. we will not touch those often on our journey so don't worry.

Next comes some resources elements which basically loads the Material Design goodies. We don't touch those either.

The line that says <Grid> is the start of our page design. It's where we define what (and how) will be shown on the app's screen. Of course at the bottom of the file there will be a closing tag </Grid> .

I recommend googling xaml and learning the basics. It's crucial for building WPF apps, regardless of the software language you use, PS or C#. But anyway I will give a short brief on what's written inside our project's file.

So, Grid is a way to divide the screen into squares. a basic grid is one square which takes the whole app's real estate. That's what we have here.

Inside our grid we put a StackPanel which is a container that it's elements will be displayed one on top of the other (by default. It can also be side by side).

We also gave the StackPanel an attribute that says: "put it in the middle of the screen vertically".

Inside the StackPanel we put a textbox, a button and a second textbox.

A textbox is an area where text can be entered and a button is... a button.

Take a look at all the attributes we put on those three elements. You can figure out what they are. The only gotcha attribute is Margin which defines the margins around the element in a clockwise direction starting at 9 o'clock. Margin="10,5,15,20" means 10pt left, 5pt up, 15pt right, 20pt bottom.

Every element that we want to interact with PowerShell needs to have a unique name on Xaml. We give it a name by typing Name="ElementName".


Note that Xaml is case sensitive as opposed to PowerShell !


Now let's look at the ps1 file:

The three [System.Reflection.Assembly] are loading Material Design and WPF.

The try-catch block is loading the content of the Xaml file into a XML type var.

Then there are two phases to load the Xaml into a format that allow WPF to actually turn this into graphical elements on the screen. $Reader and $Window. $Window will hold the information needed to show us the GUI.

The $Xaml.SelectNodes... part is creating variables out of every Xaml element that has a Name attribute in the Xaml file.

$Btn1.Add_Click is an event we attached to the button, so whenever the user clicks on it the value of the Text attribute of TextBox2 will get the value of the

Text attribute of TextBox1. Easy.

Last thing is to pop up the window, which is what $Window.ShowDialog() does.

So the only piece of code that is actually what we've written is this one liner:

$Btn1.Add_Click({$TxtBox2.Text = $TxtBox1.Text})

We rarely touch all of the other stuff you see in this ps1 file. Those parts of code will be copied from project to project.


Amazing ! We wrote our first MD based WPF GUI PS app.



893 views0 comments

Recent Posts

See All

Comentarios


bottom of page