Search code examples
wpfpowershelldata-bindinglistbox

Using PowerShell Data Binding to create a dynamic ListBox


I'm looking to create a WPF ListBox in PowerShell without loading any hard XAML (similar to the image below) that uses Data Binding to move data from one ListBox to the other when the arrow buttons are clicked. I'm still very early in the coding stage and am having difficulty conceptualizing how the various data binding components would be configured together.

  1. Hash Table: Must a separate $hash table (and corresponding $DataContext) be created for both ListBoxes?
  2. Binding: How does binding relate to moving data between the ListBoxes? Would the binding still be one-way or would it be two-way? Or would this simply be a matter of the buttons manipulating both ListBoxes independently of one another?
  3. What would be an example of a $Binding.Path in this case?

ListBox Example


Solution

  • I use a combination om hashtable and ObservableCollections for my WPF-gui's.

    First a hashtable to collect all data and bindings. It is Synchronized so that the hashtable can be used in multipel runspaces. This is sometimes needed if you want a GUI that doesn't freeze.

    $syncHash = [hashtable]::Synchronized( @{} )
    

    Then a collection for each purpose

    $syncHash.DataContext = New-Object System.Collections.ObjectModel.ObservableCollection[Object]
    

    In this collection I put values corresponding to what I will be bindning to. I like to keep the index and the purpose as a comment at the end so I can come back to it later. The index is needed later.

    $syncHash.DataContext.Add( ( New-Object System.Collections.ObjectModel.ObservableCollection[Object] ) ) # 1 All files
    

    Now its time to created the binding-objects. "Window" is the name of the variable for the WPF-window object.

    $Bindings = New-Object System.Collections.ObjectModel.ObservableCollection[Object]
    0..( $syncHash.DataContext.Count - 1 ) | foreach { [void]$Bindings.Add( ( New-Object System.Windows.Data.Binding -ArgumentList "[$_]" ) ) }
    $Bindings | foreach { $_.Mode = [System.Windows.Data.BindingMode]::TwoWay }
    $syncHash.Window.DataContext = $syncHash.DataContext
    

    Now we make the bindings to the controls and their properties. Here we need to use the same index as before, The name of the control, the type of the control and the propertyname

    [void][System.Windows.Data.BindingOperations]::SetBinding( $syncHash.lvAllFiles [System.Windows.Controls.ListView]::ItemsSourceProperty, $Bindings[1] )
    

    To work with the bindning, call the collectionname and the index then set the desired value. Like one of the following:

    $syncHash.DataContext[1] = $List
    $syncHash.DataContext[1] += "Text"
    $syncHash.DataContext[1].Add( "Text" )
    

    How you use it, depends on what kind of value you bind to (the poperty of the control) and/or what is in the DataContext-collection at that index.

    You can also make separate DataContext-collection, or different binding-collections, for each control if you want to make many bindings for many properties. This will make the administration easier, but then keep in mind The names for the bindings and/or what collection you make your bindings to.