title: Powershell Checkedlistbox handling - checked item count inconsistency and missed click events
body: <p>I'm having trouble with multiple issues with a checkedlistbox.  Its content is the Windows feature name (commandline parameter to install a Windows feature via Powershell) and a description which really is its more readable name.  Because I develop on Windows 7 and this command is only available on a Server platform I read the data from a XML file source. The XML file was created by the output of function BuildFeaturesFile, below. I've pasted a sample at the bottom if that is a problem.</p>
  
  <p>1) I have to click an item twice to check it.</p>
  
  <p>2) I have to double click an item slowly and surely to avoid the program missing the second click. Would I need to change the Windows control panel config to affect this or if I wanted (not too bothered but more curious) could I reduce the polling time to slicken the interface response?</p>
  
  <p>3) This is my main issue. If I use the mouse to select an item it normally updates the count correctly however when I use the keyboard despite calling the same function I get different results; the first check is seemingly missed (doubled by the look of it reading further online to undo its action - however the event "only" fires once which causes misalignment of the displayed count to the true count. I think it maybe linked to the remark in the ItemCheck event documentation "The check state is not updated until after the ItemCheck event occurs." 
  <a href="http://msdn.microsoft.com/en-us/library/system.windows.forms.checkedlistbox.itemcheck(v=vs.110).aspx" rel="nofollow">http://msdn.microsoft.com/en-us/library/system.windows.forms.checkedlistbox.itemcheck(v=vs.110).aspx</a>
  The main code also updates a description text box but I removed that for brevity.</p>
  
  <p>4) In function ftn_CheckAllItemsInCheckList the top remmed out line works for the first item but as I'm calling it by index seemingly the action of checking the item causes the index to change which unseats the action causing it to break.</p>
  
  <p>Please can you assist - at least with questions #3 and #4 if possible?</p>
  
  <p>Thanks in advance.</p>
  
  <p>Shaun</p>
  
  <pre><code>function BuildForm
  {
      # Declare objects
      $frm_BuildConfigurator = New-Object System.Windows.Forms.Form
      $btn_Cancel = New-Object System.Windows.Forms.Button
      $gb_CC_Features = New-Object Windows.Forms.GroupBox
      $clb_CC_Features = New-Object System.Windows.Forms.CheckedListBox
      $btn_CC_Features_UncheckList = New-Object System.Windows.Forms.Button
      $btn_CC_Features_SelectAll = New-Object System.Windows.Forms.Button
      $gb_CCF_Description = New-Object Windows.Forms.GroupBox
      $tb_CCF_Description = New-Object System.Windows.Forms.TextBox
  
      #Build the form
      $frm_BuildConfigurator.Text = "Build Configurator"
      $frm_BuildConfigurator.StartPosition = "CenterScreen"
      $frm_BuildConfigurator.Width = 380
      $frm_BuildConfigurator.Height = 200
      $frm_BuildConfigurator.FormBorderStyle = "FixedSingle"
      $frm_BuildConfigurator.ControlBox = $false
      $frm_BuildConfigurator.Controls.Add($btn_Cancel)
      #Set default button behaviour
      $frm_BuildConfigurator.KeyPreview = $True
      $frm_BuildConfigurator.Add_KeyDown({if ($_.KeyCode -eq "Enter") {$frm_BuildConfigurator.Close()}})
      $frm_BuildConfigurator.Add_KeyDown({if ($_.KeyCode -eq "Escape") {$frm_BuildConfigurator.Close()}})
  
      # Create the Cancel button
      $btn_Cancel.Location = New-Object System.Drawing.Size(50,145)
      $btn_Cancel.Size = New-Object System.Drawing.Size(55,23)
      $btn_Cancel.Text = "Cancel"
      $btn_Cancel.Add_Click({$frm_BuildConfigurator.Close()})
      # Create the Features form elements
      $frm_BuildConfigurator.Controls.Add($gb_CC_Features)
      $frm_BuildConfigurator.Controls.Add($gb_CCF_Description)
      # Create the Features group box
      $gb_CC_Features.DataBindings.DefaultDataSourceUpdateMode = [System.Windows.Forms.DataSourceUpdateMode]::OnValidation
      $gb_CC_Features.Location = New-Object System.Drawing.Point(10,6)
      $gb_CC_Features.Name = "gb_CC_Features"
      $gb_CC_Features.Size = New-Object System.Drawing.Size(350,132)
      $gb_CC_Features.Text = "Features (0 selected)"
      $gb_CC_Features.Controls.Add($clb_CC_Features)
      $gb_CC_Features.Controls.Add($btn_CC_Features_SelectAll)
      $gb_CC_Features.Controls.Add($btn_CC_Features_UncheckList)
      $clb_CC_Features.Location = New-Object Drawing.Point 11,16
      $clb_CC_Features.Size = New-Object System.Drawing.Size(220,110)
      $clb_CC_Features.Add_ItemCheck({ftnUpdateFeatureSelectionCount})
      $clb_CC_Features.Add_SelectedIndexChanged({ftnUpdateFeatureSelectionCount})
      $clb_CC_Features.Add_Click({ftnUpdateFeatureSelectionCount})
      # Populate the Features checked list box
      ForEach ($FeatureItem in $script:xmlFeatures.FeatureList.Feature | Select-Object -Property Name) {
          $clb_CC_Features.Items.Add($FeatureItem.Name) | Out-Null
      }
      # Create the Check All button
      $btn_CC_Features_SelectAll.Location = New-Object System.Drawing.Point(250,20)
      $btn_CC_Features_SelectAll.Size = New-Object System.Drawing.Size(80,23)
      $btn_CC_Features_SelectAll.Text = "Check All"
      $btn_CC_Features_SelectAll.Add_Click({ftn_CheckAllItemsInCheckList $clb_CC_Features})
      $btn_CC_Features_SelectAll.TabIndex = 2
      # Create the Uncheck All button
      $btn_CC_Features_UncheckList.Location = New-Object System.Drawing.Point(250,50)
      $btn_CC_Features_UncheckList.Size = New-Object System.Drawing.Size(80,23)
      $btn_CC_Features_UncheckList.Text = "Uncheck All"
      $btn_CC_Features_UncheckList.Add_Click({ftn_UncheckList $clb_CC_Features})
      $btn_CC_Features_UncheckList.TabIndex = 2
  
      ftnUpdateFeatureSelectionCount
      #Show the Form
      $frm_BuildConfigurator.ShowDialog() | Out-Null
  }
  
  function ftnUpdateFeatureDescription()
  {
      $tb_CCF_Description.Text = $script:FeatureDisplayNames[$clb_CC_Features.SelectedIndex]
  }
  
  function ftnUpdateFeatureSelectionCount ()
  {
      $gb_CC_Features.Text = "Features (" + $clb_CC_Features.CheckedItems.Count + " selected)"
  }
  
  function BuildFeaturesFile ()
  {
      # Only runs on Windows Server
      $Features = Get-WindowsFeature
      $xml = "&lt;xml&gt;"
      $NewFeaturesFilePath = $ScriptDir + "\FeaturesNew.xml"
      ForEach($Feature in $Features)
      {
          $xml += "&lt;Feature Name='" + $Feature.Name + "' DisplayName='" + $Feature.DisplayName + "'&gt;"
          $xml += "&lt;/Feature&gt;"
      }
      $xml += "&lt;/xml&gt;"
      $xml | Out-File -FilePath $NewFeaturesFilePath
  }
  
  function ReadFeaturesFile ()
  {
      [array] $script:FeatureNames = $null
      [array] $script:FeatureDisplayNames = $null
      $FileExists = Test-Path $FeaturesFilePath
      if ($FileExists -eq $true) {
          $script:xmlFeatures.Load($FeaturesFilePath)  
          $xml_Features = $script:xmlFeatures.SelectNodes("/FeatureList/Feature")
          ForEach ($Feature in $xml_Features) {
              [array] $script:FeatureNames += $Feature.Name
              [array] $script:FeatureDisplayNames += $Feature.DisplayName
          }
      }
  }
  
  function ftn_UncheckList( $checkedListBoxObject )
  {   
      ForEach($i in $checkedListBoxObject.CheckedIndices) { $checkedListBoxObject.SetItemCheckState($i, 'Unchecked') | Out-Null }
  }
  
  function ftn_CheckAllItemsInCheckList( $checkedListBoxObject )
  {   
      #ForEach($i in $checkedListBoxObject.Items) { $checkedListBoxObject.SetItemChecked($checkedListBoxObject.Items.IndexOf($i), $true)  }
      For($index =0; $index -lt $checkedListBoxItem.Items.Count; $index++){ if($checkedListBoxItem.GetItemChecked($index)) { $checkedListBoxItem.SetItemChecked($i, $true); }}
  }
  
  Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Force
  [void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing") 
  [void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") 
  
  $script:xmlFeatures = $null; $script:xmlFeatures = New-Object -TypeName XML
  $ScriptPath = $MyInvocation.MyCommand.Path
  $ScriptDir = Split-Path -parent $ScriptPath
  $FeaturesFilePath = $ScriptDir + "\Features.xml"
  $BuildScriptStr = $MyInvocation.MyCommand.Definition #Full path  - for script name only use $MyInvocation.MyCommand.Name
  $noSelectedFeatures = 0
  
  ReadFeaturesFile
  
  BuildForm
  
  # End of script
  </code></pre>
  
  <p>File: Features.xml</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="UTF-8" standalone="yes"?&gt;
  &lt;FeatureList&gt;
     &lt;Feature Name="AD-Certificate" DisplayName="Active Directory Certificate Services"/&gt;
     &lt;Feature Name="ADCS-Cert-Authority" DisplayName="Certification Authority"/&gt;
     &lt;Feature Name="ADCS-Web-Enrollment" DisplayName="Certification Authority Web Enrollment"/&gt;
  &lt;/FeatureList&gt;
  </code></pre>