Monday, March 20, 2017

PowerShell: Understanding Windows Forms Data Binding

Technorati Tags:
A simple example of a data bound form
I decided that it was time to post a cleaned up example of how to do data binding with PowerShell Forms.  I pulled up an old demo and set it up to use an XML extract from the NorthWind demo database.  For a demo I though that it would be better if the example could be run on any system so I have converted the form to load its data set from the XML extract.
In this post I will just point out the features and show a couple of images as well as a link to the code.
 
 
The form is intentionally simple and the colors were only changed to highlight the elements.
Features:
  • ‘Select Customer” is a live search box that autocompletes against the dataset.  Code (cost 2 line)
  • The two text box are populated with values from the selected grid row.  (code cosr one line per textbox)
  • Top navigation bar actively moves through the data set with the buttons. (code cost 3 lines.


  • Nav bar allows deleting and editing.  (code cost nothing)
  • Double clicking launches edit form.  (code cost 1 line)





















  • Edit Form doubles as a “new” record editor by adding one code line to the main form.
  • Save and cancel for edits take about 4 lines.
  • Main form detects data changes and prompts for saving.

Scripts:
The scripts are available in a Zip.  A Sapien PowerShell Studio Project is included and a PS1 file that runs without the project.
Three files are included for the forms in Demo-FormXmlDataBinding.zip
  1. Demo-FormXmlDataBinding PSS folder
  2. Standalone folder
    1. Demo-FormXmlDataBinding.ps1 –- the main file
    2. northwind.xml – the data set.
  3. The project folder is included as Demo-FormXmlDataBinding
    1. PowerShell Studio project files
Download:
Demo-FormXmlDataBinding.zip
Small code footprint:
For all of its functionality the main form contains fewer than 50 lines of code
PowerShell active code:
# Set up the form objects and bind$customerBindingSource = New-Object System.Windows.Forms.BindingSource$nav = New-Object System.Windows.Forms.BindingNavigator($true)$ds = New-Object System.Data.DataSet
# configure navigator$formXMLDataBindingExample.Controls.Add($nav)$nav.BackColor = 'LightBlue'$nav.ShowItemToolTips = $true$nav.Dock = 'top'$nav.BindingSource = $customerBindingSource
$formXMLDataBindingExample_Load={
    
    # We are loading only one table.  It is  possible to 
    # load many related tables as a relationship and they
    # will all be synchronized
    $ds.ReadXml($northwindXml)

    # We can set events on the dataset
    $ds.Tables['Customer'].add_RowChanged({ $script:modified = $true;Write-Host 'Row Changed' })
    
    # Assign the DataSet as the DataSource for the BindingSource.
    $customerBindingSource.DataSource = $ds.Tables["Customer"]
    
    # Bind to the controls.
    $textboxContactName.DataBindings.Add((New-Object System.Windows.Forms.Binding('Text', $customerBindingSource, 'ContactName', $true)))
    $textboxPhone.DataBindings.Add((New-Object System.Windows.Forms.Binding('Text', $customerBindingSource, 'Phone', $true)))
    $dgvCustomerTable.DataSource = $customerBindingSource
    $cbCompany.DataSource = $customerBindingSource
    $cbCompany.DisplayMember = 'CompanyName'
}


$dgvCustomerTable_MouseDoubleClick=[System.Windows.Forms.MouseEventHandler]{
    
    # show child form with current row data
    Show-DataChild_psf ([System.Data.DataRowView]$customerBindingSource.Current)
}

$formXMLDataBindingExample_FormClosing=[System.Windows.Forms.FormClosingEventHandler]{
    
    if($modified){
        $answer = [System.Windows.Forms.MessageBox]::Show('Do you want to save your changes and close this form?','Data has changed','YesNoCancel')
        $_.Cancel = switch ($answer){
            Yes {$ds.AcceptChanges()}
            No {$false}
            Cancel {$true}
        }
    }
    
}
Code discussion:
I will post a second and maybe third blog with a more detailed discussion of how this code works and how data binding works in Windows Forms.  Grab the RSS/Atom link and stay tuned for more.