In this post, I will show you how to add dynamic content inside a WPF window in PowerShell. Most of the time, we display dynamic data inside a Datagrid or a Listview, but what if we want to create our own display for each item?
Recently I came across this post: “Let’s play with SNCF API and Powershell!” written by Etienne Deneuve. You can get a list of the next train in a specific train station.
What‘s that got to do with us?
What‘s that got to do with us?
The answer is simple, this script will return a dynamic result for each query. And that’s a good example to use. Here is a window with a datagrid to show what we have done up until now, and a new block to show what could be done with a dynamic display.
I’ll show you step by step how to achieve something like this:
STEP 1:
Get the Grid control name where we will place our dynamic controls, and then remove everything inside.
Get the Grid control name where we will place our dynamic controls, and then remove everything inside.
$gridTrain = $Form.FindName("trainGrid")
# remove everything inside the stackpanel
$gridTrain.Children.Clear()
STEP 2:
We will create a control from within the script. If you want to create a button for example, it’s quite easy. You create a new object of type button and then add it to the control you want. For instance, the code below will add a button inside the grid identified as $gridTrain :
$Button = New-Object System.Windows.Controls.Button
$Button.Content = "Click Me"
$gridTrain.Children.Add($Button)
With this little theory, let’s create something like this:
To achieve this you have to create a certain number of elements and fully understand how stackpanel works. You can learn more about stackPanel here.
I tried to make it as simple as possible ... 😃
Finally, like we did with the button above, we just need to add each element to the parent control ($gridTrain). Something like this:
$OneTrainStackPanel.Children.Add($Rectangle) | out-Null
$OneTrainStackPanel.Children.Add($StackPanelInfos) | out-Null
# append the current train to the main Grid.
$gridTrain.Children.Add($OneTrainStackPanel) | out-Null
So that’s it for the idea! you should end up with something like this:
# We assign a Name for the stackpanel of a train
$PanelIndexName = [String]("StackPparent_"+$trainIndex )
$OneTrainStackPanel = New-StackPanel -Name $PanelIndexName -Margin "0,4,0,4" -Orientation "Horizontal" -HorizontalAlignment "Stretch" -Background "#5B965B"
# ============== The stackPanel containing infos about the train ... ==================
$StackPanelInfos = New-StackPanel -Margin "20,5,0,2" -Orientation "Vertical"
# Direction and time reamining
$directionTextBlock = New-TextBlock -Margin "0,0,0,0" -ForeGround "White"
$TimeTextBlock = New-TextBlock -Margin "0,0,0,0" -ForeGround "White"
$directionTextBlock.Text = "Direction: "+ [String]$train.direction
$TimeTextBlock.Text = "Time: " + $train.ETAinMin
# append textBlocks to the Informations StackPanel
$StackPanelInfos.Children.Add($directionTextBlock) | out-Null
$StackPanelInfos.Children.Add($TimeTextBlock) | out-Null
# =====================================================================================
# ============ The Train Icon XD ======================================================
$appbar_Train = $ApplicationResources[0].Item("appbar_train")
$VisualBrush = [System.Windows.Media.VisualBrush]::new()
$VisualBrush.Visual = $appbar_Train
$Rectangle = New-Rectangle -Margin "20,0,5,0" -Size "28,32" -VisualBrush $VisualBrush
# =====================================================================================
# Merge everything to the Train stackPanel
$OneTrainStackPanel.Height = "50"
$OneTrainStackPanel.Children.Add($Rectangle) | out-Null
$OneTrainStackPanel.Children.Add($StackPanelInfos) | out-Null
# append the current train to the main Grid.
$gridTrain.Children.Add($OneTrainStackPanel) | out-Null
New-StackPanel
New-Rectangle
New-Button
etc …
are not parts of PowerShell commands. These are commands I created to simplify things. You can find all of them here. There are still many lefts to do though.
STEP 3:
So if we have something like below to display (it’s the output of Get-NextTrain ):
Repeat the same process for each train of the array inside a big looop and that’s it, you will have the same result as shown in the preview of this post.
Where to download?
If you don’t want to grab a key for the API you can directly load the data sample on the github repository (“allTrains.csv”) with import-csv and assign it to $allTrains variable.
$script:allTrains = Import-CSV ".\allTrains.csv"
You can download the complete script here:
https://github.com/dev4sys/PsDynamicContent
Hi, i am trying to add a new label to a stackpanel that runs in a other runspace via dispatcher (eg: $SharedHash.ConnectionsPanel.Window.Dispatcher.Invoke([action]{$SharedHash.ConnectionsPanel.StackPanelTest.AddChild($SharedHash.ConnectionsPanel.Newlabel)}))
ReplyDeleteBut the shell stay stucked at this command. Any idea that is wron with that?
Greetings