Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
# Our XAML for the WPF-based GUI.
$inputXAML = @"
<Window x:Name="Pick_Console" x:Class="LetUsWPF.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:LetUsWPF"
mc:Ignorable="d"
Title="MainWindow" Height="275" Width="410">
<Grid>
<Label x:Name="label_cluster" Content="Cluster:" HorizontalAlignment="Left" Margin="10,0,0,0" VerticalAlignment="Top"/>
<ComboBox x:Name="cluster" HorizontalAlignment="Left" Margin="30,26,0,0" VerticalAlignment="Top" Width="342"/>
<Label x:Name="label_details" Content="VM Details:" HorizontalAlignment="Left" Margin="10,64,0,0" VerticalAlignment="Top"/>
<Button x:Name="console" Content="Console" HorizontalAlignment="Left" Margin="157,203,0,0" VerticalAlignment="Top" Width="75"/>
<DataGrid x:Name="details" HorizontalAlignment="Left" Margin="30,90,0,0" VerticalAlignment="Top" Height="92" Width="342" AlternationCount="1" IsReadOnly="True" SelectionMode="Single"/>
</Grid>
</Window>
"@
# Munge to remove what PowerShell doesn't like and cast as XML
# Remove design-time ignorable tags
# Convert "x:Name" nodes to "Name"
# Remove Window classing
[xml]$xaml = $inputXAML -replace 'mc:Ignorable="d"','' -replace "x:N",'N' -replace '^<Win.*', '<Window'
# Load WPF support and our XML into a form
[void][System.Reflection.Assembly]::LoadWithPartialName('presentationframework')
try {
$Form = [Windows.Markup.XamlReader]::Load((New-Object System.Xml.XmlNodeReader $xaml))
}
catch {
Write-Host "Failed to load Windows.Markup.XamlReader. Invalid XML?"
exit
}
# Load XAML Objects into variables
$xaml.SelectNodes("//*[@Name]") |
Where-Object { $_.Name -notlike "label_*" } |
ForEach-Object { Set-Variable -Name "WPF_$($_.Name)" -Value $Form.FindName($_.Name) }
#
# Event Handlers for our WPF controls
#
# WPF form is loaded
$Form.Add_Loaded({
# Connect to vCenter and populate the list of clusters
Connect-VIServer $vCenter
Get-Cluster | ForEach-Object { $WPF_cluster.Items.Add($_.Name) }
$WPF_console.IsEnabled = $false # No sense in clicking the button yet!
})
# A Cluster selection is made in the Cluster ComboBox
$WPF_cluster.Add_SelectionChanged({
# On selection of a cluster, populate the list of VMs. The DataGrid control
# requires an ArrayList for loading
$VM_array = New-Object System.Collections.ArrayList
$VMs = Get-Cluster $WPF_cluster.SelectedValue | Get-VM |Select-Object Name, PowerState, NumCPU, MemoryGB | Sort-Object Name
$VM_array.AddRange($VMs)
$WPF_details.clear() # Clear any prior values
$WPF_details.ItemsSource = $VM_array # Load our new values
$WPF_details.IsReadOnly = $true # No, these aren't editable
# Allow sorting on all columns
$WPF_details.Columns | ForEach-Object { $_.CanUserSort = $true }
})
# VM Selection is made in the details DataGrid
$WPF_details.Add_SelectionChanged({
# Console option is present if VM is on
$WPF_console.IsEnabled = ($WPF_details.SelectedItems -ne $null) -and
($WPF_details.SelectedValue.PowerState -eq "PoweredOn")
})
# Take action on pressing the Console button
$WPF_console.Add_Click({
Open-VMConsoleWindow -VM $WPF_details.SelectedValue.Name
$WPF_console.IsEnabled = $false # Disable until next choice
})
# WPF for is closed
$Form.Add_Closed({
Disconnect-VIServer $vCenter -Confirm:$false
})
#
# Variables that you can/should change
#
$vCenter = "my-vcsa"
# Present!
$form.ShowDialog() | Out-Null

Can you update the window title with the $vCenter name?

edycus commented Nov 24, 2015

Loved your exmaple, I have been looking for an example of using xaml form and datgrid. This is the only one I found. It helped me alot with my code. Good job.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment