Monday 2 April 2018

Powershell_WPF - Part V - Display Dynamic content



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?

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.


      $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.
Here is a little explanation of the “thing”:
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


I added two textblock for train info but what’s important to understand is the theory behind the wheel. Please note that:
   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 hereThere 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

Share:

1 comment:

  1. 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)}))
    But the shell stay stucked at this command. Any idea that is wron with that?
    Greetings

    ReplyDelete

Popular Posts

Join us on Facebook

STATS

Contact Form

Name

Email *

Message *