Using XAML/WPF in PowerShell, how do I populate a list box? Using XAML/WPF in PowerShell, how do I populate a list box? powershell powershell

Using XAML/WPF in PowerShell, how do I populate a list box?


Alright, I figured out the answer. It turns out that when I was using .Add, I should have been specifying a PowerShell custom object as my overload, not a simple hashtable as I was doing before. When I changed my code to the following:

#Add DisplayMemberBindings for all columns<GridViewColumn Header="VMName" DisplayMemberBinding ="{Binding VMName}"/><GridViewColumn Header="Status" DisplayMemberBinding ="{Binding Status}"/><GridViewColumn Header="Other" DisplayMemberBinding ="{Binding Other}"/>

And then modify my Add statement as well:

$vmpicklistView.items.Add([pscustomobject]@{'VMName'='1';Status="Access Denied";Other="Yes"})

I'm able to populate my fields, like so

#Make Dummy Entries 1..15 | % {if ($_ % 2){$vmpicklistView.items.Add([pscustomobject]@{'VMName'="VM_$($_)";Status="Online";Other="Yes"})}else{$vmpicklistView.items.Add([pscustomobject]@{'VMName'="VM_$($_)";Status="Access Denied";Other="Yes"})}}

enter image description here

Why did I have to do this?

Here is my interpretation as to why this was needed. PowerShell Custom Objects provide an Object with Named values, which I can pluck out using bindings, while a hashtable is a collection of Key/Value pairs, not well suited for this purpose.

I hope this answer has helped anyone else who got stumped as I did!


WPF is generally used to bind to viewmodel object properties not dictionary or hashtable entries. There is a syntax to bind to dictionary entries which would make the GridViewColumn bindings look like this:

<GridViewColumn Header="VMName" DisplayMemberBinding ="{Binding [VMName]}"/><GridViewColumn Header="Status" DisplayMemberBinding ="{Binding [Status]}"/>

Note the use of square brackets to indicate that the value comes from an indexer.

As for why the "Other" column appears as "(Collection)", I believe the default binding is just going to display the object and WPF must render dictionaries and hashtables as "(Collection)"

Try adding a similar binding for Other:

<GridViewColumn Header="Other" DisplayMemberBinding ="{Binding [Other]}"/>


There is a much simpler way of doing this.

Say you have a setup similar to the question above

<ListView Name="Collections">  <ListView.View>    <GridView>      <GridViewColumn Header="Collection Name" DisplayMemberBinding="{Binding CollectionName}" />      <GridViewColumn Header="Collection Count" DisplayMemberBinding="{Binding CollectionCount}" />    </GridView>  </ListView.View></ListView>

and in Powershell you are getting say the list of objects from some provider (in this case ConfigurationManager)

$DCs = Get-CMDeviceCollection | ? { $_.CollectionRules.RuleName -contains "OU Query" } 

Now this out of the box has properties that do not align with my DisplayMemberBindings so we have to make a collection of objects that do so

$BindableDCs = $DCs | Select-Object -Property @{Name='CollectionName';Expression={$_.Name}}, @{Name='CollectionCount';Expression={$_.MemberCount}}

Now (assuming the code to load the XAML and discover the named elements and put them in powershell variables has been run)

$Collections.ItemsSource = $BindableDCs

Done.

Or if you want to do it the one liner powershell way

$Collections.ItemsSource = Get-CMDeviceCollection | ? { $_.CollectionRules.RuleName -contains "OU Query" } | Select-Object -Property @{Name='CollectionName';Expression={$_.Name}}, @{Name='CollectionCount';Expression={$_.MemberCount}}