Hey, Scripting Guy! How Can I Use the Windows Forms TreeView Control?

Hey, Scripting Guy! How Can I Use the Windows Forms TreeView Control?

  • Comments 4
  • Likes

Bookmark and Share

Today we have a guest article by Ravikanth who works at Dell, Inc., as a lead engineer in the SharePoint Solutions Team. He loves automation and is a Windows PowerShell fanatic. He writes regularly on his blog about topics related to Windows PowerShell, SharePoint, and Microsoft server virtualization. He is also moderator on the Official Hey, Scripting Guy! Forum and a regular speaker at BangaloreITPro User Group meetings.

 

In today’s post, we will see an example of how to use Windows Forms TreeView control. I will explain this by showing an example of a Windows PowerShell help tree.

First, we design a simple GUI form using SAPIEN’s PrimalForms Community Edition. I placed the TreeView control, a rich text box, a link label, and a button. This is seen in the image following this paragraph. The intention of this form is to load the Windows PowerShell help for all Windows PowerShell core modules in the form of a tree, and when you select a cmdlet within the tree, help text for that cmdlet will be shown in the text box along with a link to a TechNet article at the bottom of the form.

Image of simple GUI form

After the design is complete, we export the form to a Windows PowerShell script using Export PowerShell option. This generates the necessary code to create the GUI form in Windows PowerShell. Now, we need to edit this script to add the custom code we need to create our process manager:

  • We need to perform the following script changes to make the Windows PowerShell help tree complete.
  • We need a list of Windows PowerShell core modules to display.
  • We need to build the tree and define what should happen when someone clicks on the nodes of the tree.

Before we go further in to the details of this script, let us quickly look at how the TreeView control is created. The following snippet shows the code generated by PrimalForms to add the TreeView control to the main form:

$treeView1 = New-Object System.Windows.Forms.TreeView
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Width = 224
$System_Drawing_Size.Height = 563
$treeView1.Size = $System_Drawing_Size
$treeView1.Name = "treeView1"
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 13
$System_Drawing_Point.Y = 37
$treeView1.Location = $System_Drawing_Point
$treeView1.DataBindings.DefaultDataSourceUpdateMode = 0
$treeView1.TabIndex = 0
$form1.Controls.Add($treeView1)

We use the System.Windows.Forms.TreeView namespace to create an instance as $treeView1. After this instance is created, we assign values to properties such as size, name, and various other properties. Now, we need to build the tree and show it as the form loads.

To build the Windows PowerShell help tree, we create a function and add it to the Form Load event—$form1.Add_Load().

The following section of code shows the function we created to build the Windows PowerShell help tree:

function Get-HelpTree {
if ($script:cmdletNodes)
{
$treeview1.Nodes.remove($script:cmdletNodes)
$form1.Refresh()
}
$script:cmdletNodes = New-Object System.Windows.Forms.TreeNode
$script:cmdletNodes.text = "PowerShell Help"
$script:cmdletNodes.Name = "PowerShell Help"
$script:cmdletNodes.Tag = "root"
$treeView1.Nodes.Add($script:cmdletNodes) | Out-Null
#Generate Module nodes
$modules = @("Microsoft.PowerShell.Core","Microsoft.PowerShell.Diagnostics","Microsoft.PowerShell.Host","Microsoft.PowerShell.Management","Microsoft.PowerShell.Security","Microsoft.PowerShell.Utility")
$modules | % {
$parentNode = Add-Node $script:cmdletNodes $_ "Module"
$moduleCmdlets = Get-Command -Module $_
$moduleCmdlets | % {
$childNode = Add-Node $parentNode $_.Name "Cmdlet"
}
}
$treeView1.add_AfterSelect({
if ($this.SelectedNode.Tag -eq "Cmdlet") {
$helpText = Get-Help $this.SelectedNode.Name -Full
$richTextBox1.Text = $helpText | Out-String
$linkLabel1.Text = $helpText.relatedLinks.navigationLink[0].uri
$form1.refresh()
} else {
$richTextBox1.Text = "Example to show how to use TreeView control in PowerShell script"
$linkLabel1.Text = "http://www.ravichaganti.com/blog"
}
})
$script:cmdletNodes.Expand()
}

Let us now explore how the above function is building our Windows PowerShell tree. First, we add the root of the tree and call it “PowerShell Help”. Underneath this, we build help for all the Windows PowerShell core modules as different nodes. The first part is achieved by:

$script:cmdletNodes = New-Object System.Windows.Forms.TreeNode

$script:cmdletNodes.text = "PowerShell Help"

$script:cmdletNodes.Name = "PowerShell Help"

$script:cmdletNodes.Tag = "root"

Notice that I am using the Tag property to identify the node. In this case, the Tag property for root node is set to root for obvious reasons. You will later see why this is so important.

Now, we need to generate the rest of the tree and child nodes. For that we need to know which Windows PowerShell core modules are available, and the easiest way to achieve that is to store all the module names in an array as shown here:

$modules = @("Microsoft.PowerShell.Core","Microsoft.PowerShell.Diagnostics","Microsoft.PowerShell.Host","Microsoft.PowerShell.Management","Microsoft.PowerShell.Security","Microsoft.PowerShell.Utility")

The $modules variable has a list of all Windows PowerShell core modules. We can now use this to generate the child nodes. To do that, we use the Get-Command cmdlet to get a list of all cmdlets provided by each of the above Windows PowerShell modules, and then add the names of those cmdlets to the TreeView as child nodes:

$modules | % {

$parentNode = Add-Node $script:cmdletNodes $_ "Module"

$moduleCmdlets = Get-Command -Module $_

$moduleCmdlets | % {

$childNode = Add-Node $parentNode $_.Name "Cmdlet"

}

}

To simplify the script and enable re-use, we added another function to our script and called it Add-Node. This function will be called recursively to generate the child nodes as required:

function Add-Node {

param (

$selectedNode,

$name,

$tag

)

$newNode = new-object System.Windows.Forms.TreeNode

$newNode.Name = $name

$newNode.Text = $name

$newNode.Tag = $tag

$selectedNode.Nodes.Add($newNode) | Out-Null

return $newNode

}

We pass the node name and a tag associated with the node to the Add-Node function. Notice, again, that we are using tags to differentiate several levels of our Windows PowerShell tree. In this case, all the module names use Module as the tag name and cmdlets underneath a module use Cmdlet.

After we have the entire tree built, we need to define what should happen when someone selects a node or cmdlet within our tree. In this example, as mentioned earlier, when a cmdlet gets selected in the tree, we display complete help text for the cmdlet in the text box. This is achieved by adding the necessary code to the After_Select() event of every node:

$treeView1.add_AfterSelect({

if ($this.SelectedNode.Tag -eq "Cmdlet") {

$helpText = Get-Help $this.SelectedNode.Name -Full

$richTextBox1.Text = $helpText | Out-String

$linkLabel1.Text = $helpText.relatedLinks.navigationLink[0].uri

$form1.refresh()

} else {

$richTextBox1.Text = "Example to show how to use TreeView control in PowerShell script"

$linkLabel1.Text = "http://www.ravichaganti.com/blog"

}

})

In the above code, observe how we are checking if the selected node is a cmdlet or not. This is the reason why we need to use the Tag property at every level of the tree we generated. It helps us identify what has been selected and take an action based on that. In the case when the selected node is a cmdlet, we use the node name along with the Get-Help cmdlet to generate the help and display the same in the form’s text box.

Also, we refresh the link label at the bottom of the form to point to the online version of help for the selected cmdlet. This link label can be clicked to open an Internet browser and reach the online help version for the selected cmdlet. This is achieved by adding the necessary code as shown here:

$linkLabel1.add_click($linkLabel1_OpenLink)

$linkLabel1_OpenLink=

{

[system.Diagnostics.Process]::start($linkLabel1.text)

}

In case of nodes other than Cmdlets, we just default the values to something as shown above. In the end, we enable a Close button by adding $form1.Close() to $button1.Add_Close() event.

You can find the complete code for this article in the Script Repository. You can also see a bit more advanced example of data grid control along with TreeView control in the Windows PowerShell remote file explorer script at http://psremoteexplorer.codeplex.com/

 

Well, scripters, that is all there is to using Windows Forms TreeView control. Guest Blogger Week will continue tomorrow.

If you want to know exactly what we will be looking at tomorrow, follow us on Twitter or Facebook. If you have any questions, send e-mail to us at scripter@microsoft.com or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson and Craig Liebendorfer, Scripting Guys

 

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • There's a typo in the link at the end. Its PsRemoteExplorer   the O and M in remote got switched round

  • Thanks Jamesone, we have corrected the spelling.

  • Is there a way to determine the expand(+) and collapse(-) treenode clicks i.e. which node on Add_AfterCollapse/Expand events?

    .SelectedNode is not the answer...

  • Using TreeView Control for WinForms at design time,
    http://www.kettic.com/winforms_ui/treeview.shtml