diff --git a/FFUDevelopment/BuildFFUVM_UI.ps1 b/FFUDevelopment/BuildFFUVM_UI.ps1
index 2a79b99..dbf1877 100644
--- a/FFUDevelopment/BuildFFUVM_UI.ps1
+++ b/FFUDevelopment/BuildFFUVM_UI.ps1
@@ -205,7 +205,6 @@ $window.Add_Loaded({
$script:uiState.Controls.chkSelectSpecificUSBDrives.IsEnabled = $false
$script:uiState.Controls.chkSelectSpecificUSBDrives.IsChecked = $false
$script:uiState.Controls.lstUSBDrives.Items.Clear()
- $script:uiState.Controls.chkSelectAllUSBDrives.IsChecked = $false
})
$script:uiState.Controls.chkSelectSpecificUSBDrives.Add_Checked({
$script:uiState.Controls.usbSelectionPanel.Visibility = 'Visible'
@@ -213,7 +212,6 @@ $window.Add_Loaded({
$script:uiState.Controls.chkSelectSpecificUSBDrives.Add_Unchecked({
$script:uiState.Controls.usbSelectionPanel.Visibility = 'Collapsed'
$script:uiState.Controls.lstUSBDrives.Items.Clear()
- $script:uiState.Controls.chkSelectAllUSBDrives.IsChecked = $false
})
$script:uiState.Controls.chkSelectSpecificUSBDrives.IsEnabled = $script:uiState.Controls.chkBuildUSBDriveEnable.IsChecked
$script:uiState.Controls.chkAllowExternalHardDiskMedia.Add_Checked({
@@ -961,8 +959,8 @@ $btnLoadConfig.Add_Click({
# Update the ListView's ItemsSource after populating the data list
$lstAppsScriptVars.ItemsSource = $script:uiState.Data.appsScriptVariablesDataList.ToArray()
# Update the header checkbox state
- if ($null -ne (Get-Variable -Name 'chkSelectAllAppsScriptVariables' -Scope Script -ErrorAction SilentlyContinue)) {
- Update-SelectAllHeaderCheckBoxState -ListView $lstAppsScriptVars -HeaderCheckBox $script:chkSelectAllAppsScriptVariables
+ if ($null -ne $script:uiState.Controls.chkSelectAllAppsScriptVariables) {
+ Update-SelectAllHeaderCheckBoxState -ListView $lstAppsScriptVars -HeaderCheckBox $script:uiState.Controls.chkSelectAllAppsScriptVariables
}
# Update USB Drive selection if present in config
@@ -1016,9 +1014,11 @@ $btnLoadConfig.Add_Click({
}
$script:uiState.Controls.lstUSBDrives.Items.Refresh()
- # Update the Select All checkbox state
- $allSelected = $script:uiState.Controls.lstUSBDrives.Items.Count -gt 0 -and -not ($script:uiState.Controls.lstUSBDrives.Items | Where-Object { -not $_.IsSelected })
- $script:uiState.Controls.chkSelectAllUSBDrives.IsChecked = $allSelected
+ # Update the Select All header checkbox state
+ $headerChk = $script:uiState.Controls.chkSelectAllUSBDrivesHeader
+ if ($null -ne $headerChk) {
+ Update-SelectAllHeaderCheckBoxState -ListView $script:uiState.Controls.lstUSBDrives -HeaderCheckBox $headerChk
+ }
WriteLog "LoadConfig: USBDriveList processing complete."
}
else {
diff --git a/FFUDevelopment/BuildFFUVM_UI.xaml b/FFUDevelopment/BuildFFUVM_UI.xaml
index 335014d..626c140 100644
--- a/FFUDevelopment/BuildFFUVM_UI.xaml
+++ b/FFUDevelopment/BuildFFUVM_UI.xaml
@@ -198,19 +198,12 @@
-
-
-
-
-
-
-
-
+
diff --git a/FFUDevelopment/FFUUI.Core/FFUUI.Core.Handlers.psm1 b/FFUDevelopment/FFUUI.Core/FFUUI.Core.Handlers.psm1
index 7c0d4ef..9050699 100644
--- a/FFUDevelopment/FFUUI.Core/FFUUI.Core.Handlers.psm1
+++ b/FFUDevelopment/FFUUI.Core/FFUUI.Core.Handlers.psm1
@@ -12,30 +12,23 @@ function Register-EventHandlers {
$localState.Controls.lstUSBDrives.Items.Clear()
$usbDrives = Get-USBDrives
foreach ($drive in $usbDrives) {
- $localState.Controls.lstUSBDrives.Items.Add([PSCustomObject]$drive)
+ $driveObject = [PSCustomObject]$drive
+ # Explicitly add and initialize the IsSelected property for each new item.
+ $driveObject | Add-Member -MemberType NoteProperty -Name 'IsSelected' -Value $false -Force
+ $localState.Controls.lstUSBDrives.Items.Add($driveObject)
}
if ($localState.Controls.lstUSBDrives.Items.Count -gt 0) {
$localState.Controls.lstUSBDrives.SelectedIndex = 0
}
- })
-
- $State.Controls.chkSelectAllUSBDrives.Add_Checked({
- param($eventSource, $routedEventArgs)
- $window = [System.Windows.Window]::GetWindow($eventSource)
- $localState = $window.Tag
- foreach ($item in $localState.Controls.lstUSBDrives.Items) { $item.IsSelected = $true }
- $localState.Controls.lstUSBDrives.Items.Refresh()
- })
- $State.Controls.chkSelectAllUSBDrives.Add_Unchecked({
- param($eventSource, $routedEventArgs)
- # This event also fires for indeterminate state, so only act if it's explicitly false.
- if ($eventSource.IsChecked -eq $false) {
- $window = [System.Windows.Window]::GetWindow($eventSource)
- $localState = $window.Tag
- foreach ($item in $localState.Controls.lstUSBDrives.Items) { $item.IsSelected = $false }
- $localState.Controls.lstUSBDrives.Items.Refresh()
+ WriteLog "Check USB Drives: Found $($localState.Controls.lstUSBDrives.Items.Count) USB drives."
+ # After clearing and repopulating, update the 'Select All' header checkbox state
+ $headerChk = $localState.Controls.chkSelectAllUSBDrivesHeader
+ if ($null -ne $headerChk) {
+ Update-SelectAllHeaderCheckBoxState -ListView $localState.Controls.lstUSBDrives -HeaderCheckBox $headerChk
}
})
+
+
$State.Controls.lstUSBDrives.Add_KeyDown({
param($eventSource, $keyEvent)
if ($keyEvent.Key -eq 'Space') {
@@ -45,10 +38,11 @@ function Register-EventHandlers {
if ($selectedItem) {
$selectedItem.IsSelected = -not $selectedItem.IsSelected
$localState.Controls.lstUSBDrives.Items.Refresh()
- # After toggling, update the 'Select All' checkbox state
- $items = $localState.Controls.lstUSBDrives.Items
- $allSelected = $items.Count -gt 0 -and ($items | Where-Object { -not $_.IsSelected }).Count -eq 0
- $localState.Controls.chkSelectAllUSBDrives.IsChecked = $allSelected
+ # After toggling, update the 'Select All' header checkbox state
+ $headerChk = $localState.Controls.chkSelectAllUSBDrivesHeader
+ if ($null -ne $headerChk) {
+ Update-SelectAllHeaderCheckBoxState -ListView $localState.Controls.lstUSBDrives -HeaderCheckBox $headerChk
+ }
}
}
})
@@ -56,10 +50,11 @@ function Register-EventHandlers {
param($eventSource, $selChangeEvent)
$window = [System.Windows.Window]::GetWindow($eventSource)
$localState = $window.Tag
- $items = $localState.Controls.lstUSBDrives.Items
- # Update the 'Select All' checkbox state based on current selections
- $allSelected = $items.Count -gt 0 -and ($items | Where-Object { -not $_.IsSelected }).Count -eq 0
- $localState.Controls.chkSelectAllUSBDrives.IsChecked = $allSelected
+ # Update the 'Select All' header checkbox state based on current selections
+ $headerChk = $localState.Controls.chkSelectAllUSBDrivesHeader
+ if ($null -ne $headerChk) {
+ Update-SelectAllHeaderCheckBoxState -ListView $localState.Controls.lstUSBDrives -HeaderCheckBox $headerChk
+ }
})
# Hyper-V tab event handlers
diff --git a/FFUDevelopment/FFUUI.Core/FFUUI.Core.Initialize.psm1 b/FFUDevelopment/FFUUI.Core/FFUUI.Core.Initialize.psm1
index b52a905..098cbbb 100644
--- a/FFUDevelopment/FFUUI.Core/FFUUI.Core.Initialize.psm1
+++ b/FFUDevelopment/FFUUI.Core/FFUUI.Core.Initialize.psm1
@@ -37,7 +37,6 @@ function Initialize-UIControls {
$State.Controls.chkPreviewCU = $window.FindName('chkUpdatePreviewCU')
$State.Controls.btnCheckUSBDrives = $window.FindName('btnCheckUSBDrives')
$State.Controls.lstUSBDrives = $window.FindName('lstUSBDrives')
- $State.Controls.chkSelectAllUSBDrives = $window.FindName('chkSelectAllUSBDrives')
$State.Controls.chkBuildUSBDriveEnable = $window.FindName('chkBuildUSBDriveEnable')
$State.Controls.usbSection = $window.FindName('usbDriveSection')
$State.Controls.chkSelectSpecificUSBDrives = $window.FindName('chkSelectSpecificUSBDrives')
@@ -254,7 +253,7 @@ function Initialize-DynamicUIElements {
$State.Controls.lstDriverModels.View = $driverModelsGridView # Assign GridView to ListView first
# Add the selectable column using the new function
- Add-SelectableGridViewColumn -ListView $State.Controls.lstDriverModels -HeaderCheckBoxScriptVariableName "chkSelectAllDriverModels" -ColumnWidth 70
+ Add-SelectableGridViewColumn -ListView $State.Controls.lstDriverModels -State $State -HeaderCheckBoxKeyName "chkSelectAllDriverModels" -ColumnWidth 70
# Add other sortable columns with left-aligned headers
Add-SortableColumn -gridView $driverModelsGridView -header "Make" -binding "Make" -width 100 -headerHorizontalAlignment Left
@@ -286,7 +285,7 @@ function Initialize-DynamicUIElements {
$State.Controls.lstWingetResults.ItemContainerStyle = $itemStyleWingetResults
# Add the selectable column using the new function
- Add-SelectableGridViewColumn -ListView $State.Controls.lstWingetResults -HeaderCheckBoxScriptVariableName "chkSelectAllWingetResults" -ColumnWidth 60
+ Add-SelectableGridViewColumn -ListView $State.Controls.lstWingetResults -State $State -HeaderCheckBoxKeyName "chkSelectAllWingetResults" -ColumnWidth 60
# Add other sortable columns with left-aligned headers
Add-SortableColumn -gridView $wingetGridView -header "Name" -binding "Name" -width 200 -headerHorizontalAlignment Left
@@ -322,7 +321,7 @@ function Initialize-DynamicUIElements {
# The GridView for lstAppsScriptVariables is defined in XAML. We need to get it and add the column.
if ($State.Controls.lstAppsScriptVariables.View -is [System.Windows.Controls.GridView]) {
- Add-SelectableGridViewColumn -ListView $State.Controls.lstAppsScriptVariables -HeaderCheckBoxScriptVariableName "chkSelectAllAppsScriptVariables" -ColumnWidth 60
+ Add-SelectableGridViewColumn -ListView $State.Controls.lstAppsScriptVariables -State $State -HeaderCheckBoxKeyName "chkSelectAllAppsScriptVariables" -ColumnWidth 60
# Make Key and Value columns sortable
$appsScriptVarsGridView = $State.Controls.lstAppsScriptVariables.View
@@ -375,6 +374,70 @@ function Initialize-DynamicUIElements {
else {
WriteLog "Initialize-DynamicUIElements: Could not build features grid. Panel or defaults missing."
}
+
+ # USB Drives ListView setup
+ # Set ListViewItem style to stretch content horizontally so cell templates fill the cell
+ $itemStyleUSBDrives = New-Object System.Windows.Style([System.Windows.Controls.ListViewItem])
+ $itemStyleUSBDrives.Setters.Add((New-Object System.Windows.Setter([System.Windows.Controls.ListViewItem]::HorizontalContentAlignmentProperty, [System.Windows.HorizontalAlignment]::Stretch)))
+ $State.Controls.lstUSBDrives.ItemContainerStyle = $itemStyleUSBDrives
+
+ if ($State.Controls.lstUSBDrives.View -is [System.Windows.Controls.GridView]) {
+ # Add the selectable column using the shared function
+ Add-SelectableGridViewColumn -ListView $State.Controls.lstUSBDrives -State $State -HeaderCheckBoxKeyName "chkSelectAllUSBDrivesHeader" -ColumnWidth 70
+
+ # Make other columns sortable
+ $usbDrivesGridView = $State.Controls.lstUSBDrives.View
+
+ # Model Column (index 0 in XAML, now 1)
+ if ($usbDrivesGridView.Columns.Count -gt 1) {
+ $modelColumn = $usbDrivesGridView.Columns[1]
+ $modelHeader = New-Object System.Windows.Controls.GridViewColumnHeader
+ $modelHeader.Content = "Model"
+ $modelHeader.Tag = "Model" # Property to sort by
+ $modelHeader.HorizontalContentAlignment = [System.Windows.HorizontalAlignment]::Left
+ $modelColumn.Header = $modelHeader
+ }
+
+ # Serial Number Column (index 1 in XAML, now 2)
+ if ($usbDrivesGridView.Columns.Count -gt 2) {
+ $serialColumn = $usbDrivesGridView.Columns[2]
+ $serialHeader = New-Object System.Windows.Controls.GridViewColumnHeader
+ $serialHeader.Content = "Serial Number"
+ $serialHeader.Tag = "SerialNumber" # Property to sort by
+ $serialHeader.HorizontalContentAlignment = [System.Windows.HorizontalAlignment]::Left
+ $serialColumn.Header = $serialHeader
+ }
+
+ # Size Column (index 2 in XAML, now 3)
+ if ($usbDrivesGridView.Columns.Count -gt 3) {
+ $sizeColumn = $usbDrivesGridView.Columns[3]
+ $sizeHeader = New-Object System.Windows.Controls.GridViewColumnHeader
+ $sizeHeader.Content = "Size (GB)"
+ $sizeHeader.Tag = "Size" # Property to sort by
+ $sizeHeader.HorizontalContentAlignment = [System.Windows.HorizontalAlignment]::Left
+ $sizeColumn.Header = $sizeHeader
+ }
+
+ # Add Click event handler for sorting
+ $State.Controls.lstUSBDrives.AddHandler(
+ [System.Windows.Controls.GridViewColumnHeader]::ClickEvent,
+ [System.Windows.RoutedEventHandler] {
+ param($eventSource, $e) # $eventSource is the ListView control
+ $header = $e.OriginalSource
+ if ($header -is [System.Windows.Controls.GridViewColumnHeader] -and $header.Tag) {
+ # Retrieve the main UI state object from the window's Tag property
+ $listViewControl = $eventSource
+ $window = [System.Windows.Window]::GetWindow($listViewControl)
+ $uiStateFromWindowTag = $window.Tag
+
+ Invoke-ListViewSort -listView $eventSource -property $header.Tag -State $uiStateFromWindowTag
+ }
+ }
+ )
+ }
+ else {
+ WriteLog "Warning: lstUSBDrives.View is not a GridView. Selectable column not added, and sorting cannot be enabled."
+ }
}
function Initialize-VMSwitchData {
diff --git a/FFUDevelopment/FFUUI.Core/FFUUI.Core.Shared.psm1 b/FFUDevelopment/FFUUI.Core/FFUUI.Core.Shared.psm1
index e0673c8..6686e9e 100644
--- a/FFUDevelopment/FFUUI.Core/FFUUI.Core.Shared.psm1
+++ b/FFUDevelopment/FFUUI.Core/FFUUI.Core.Shared.psm1
@@ -283,7 +283,9 @@ function Add-SelectableGridViewColumn {
[Parameter(Mandatory)]
[System.Windows.Controls.ListView]$ListView,
[Parameter(Mandatory)]
- [string]$HeaderCheckBoxScriptVariableName,
+ [psobject]$State,
+ [Parameter(Mandatory)]
+ [string]$HeaderCheckBoxKeyName,
[Parameter(Mandatory)]
[double]$ColumnWidth,
[string]$IsSelectedPropertyName = "IsSelected"
@@ -335,8 +337,8 @@ function Add-SelectableGridViewColumn {
}
})
- Set-Variable -Name $HeaderCheckBoxScriptVariableName -Value $headerCheckBox -Scope Script -Force
- WriteLog "Add-SelectableGridViewColumn: Stored header checkbox in script variable '$HeaderCheckBoxScriptVariableName'."
+ $State.Controls[$HeaderCheckBoxKeyName] = $headerCheckBox
+ WriteLog "Add-SelectableGridViewColumn: Stored header checkbox in State.Controls with key '$HeaderCheckBoxKeyName'."
$selectableColumn = New-Object System.Windows.Controls.GridViewColumn
$selectableColumn.Header = $headerCheckBox
@@ -354,8 +356,8 @@ function Add-SelectableGridViewColumn {
# MODIFICATION: Store the actual ListView object in the item checkbox's Tag
$tagObject = [PSCustomObject]@{
- HeaderCheckboxName = $HeaderCheckBoxScriptVariableName
- ListViewControl = $ListView # Store the object itself
+ HeaderCheckboxKeyName = $HeaderCheckBoxKeyName
+ ListViewControl = $ListView # Store the object itself
}
$checkBoxFactory.SetValue([System.Windows.FrameworkElement]::TagProperty, $tagObject)
@@ -364,17 +366,25 @@ function Add-SelectableGridViewColumn {
$itemCheckBox = $eventSourceLocal -as [System.Windows.Controls.CheckBox]
$tagData = $itemCheckBox.Tag
- $headerCheckboxNameFromTag = $tagData.HeaderCheckboxName
+ $headerCheckboxKeyFromTag = $tagData.HeaderCheckboxKeyName
$targetListView = $tagData.ListViewControl # Get the control directly from the tag
- WriteLog "Add-SelectableGridViewColumn: Item Click. ListView: '$($targetListView.Name)', HeaderChkName: '$headerCheckboxNameFromTag'"
+ # Get the state from the window tag
+ $window = [System.Windows.Window]::GetWindow($targetListView)
+ if ($null -eq $window -or $null -eq $window.Tag) {
+ WriteLog "Add-SelectableGridViewColumn: ERROR - Could not get window or state from window tag."
+ return
+ }
+ $localState = $window.Tag
- $headerChk = Get-Variable -Name $headerCheckboxNameFromTag -Scope Script -ValueOnly -ErrorAction SilentlyContinue
+ WriteLog "Add-SelectableGridViewColumn: Item Click. ListView: '$($targetListView.Name)', HeaderChkKey: '$headerCheckboxKeyFromTag'"
+
+ $headerChk = $localState.Controls[$headerCheckboxKeyFromTag]
if ($null -ne $headerChk) {
Update-SelectAllHeaderCheckBoxState -ListView $targetListView -HeaderCheckBox $headerChk
}
else {
- WriteLog "Add-SelectableGridViewColumn: Error - Could not retrieve script variable for header checkbox named '$headerCheckboxNameFromTag'."
+ WriteLog "Add-SelectableGridViewColumn: Error - Could not retrieve header checkbox from state with key '$headerCheckboxKeyFromTag'."
}
})
@@ -411,7 +421,9 @@ function Update-SelectAllHeaderCheckBoxState {
}
$selectedCount = ($collectionToInspect | Where-Object { $_.IsSelected }).Count
+ WriteLog "Update-SelectAllHeaderCheckBoxState: Selected count is $selectedCount for ListView '$($ListView.Name)'."
$totalItemCount = $collectionToInspect.Count # Get the total count from the collection being inspected
+ WriteLog "Update-SelectAllHeaderCheckBoxState: Total item count is $totalItemCount for ListView '$($ListView.Name)'."
if ($totalItemCount -eq 0) {
# Handle empty list case specifically