mirror of
https://github.com/rbalsleyMSFT/FFU.git
synced 2026-06-13 18:07:20 -06:00
4a2d8e63ea
Introduces new parameters and UI controls to give users more choice over device naming when applying an Unattend.xml file. Users can now specify a device name, use a static or template-based name with the `%serial%` variable, or continue using a list of prefixes. The UI is updated with a new Device Naming expander to guide the user through the options and clearly indicate the requirements for each mode, ensuring that mutually exclusive options like Copy Unattend and Inject Unattend are not selected together. Documentation is updated to reflect the new functionality.
977 lines
60 KiB
PowerShell
977 lines
60 KiB
PowerShell
<#
|
|
.SYNOPSIS
|
|
Initializes the user interface for the BuildFFUVM_UI application.
|
|
|
|
.DESCRIPTION
|
|
This script module contains functions responsible for initializing the WPF user interface.
|
|
It handles several key tasks:
|
|
- Caching references to all UI controls for efficient access.
|
|
- Populating UI elements like combo boxes with data (e.g., Hyper-V switches).
|
|
- Setting default values for all controls based on configuration or predefined settings.
|
|
- Dynamically creating and configuring complex UI components, such as sortable/selectable GridView columns and feature selection grids.
|
|
|
|
This module is critical for setting up the initial state of the application window when it first loads.
|
|
#>
|
|
|
|
function Initialize-FluentTheme {
|
|
param(
|
|
[Parameter(Mandatory = $true)]
|
|
[System.Windows.Window]$Window,
|
|
[Parameter(Mandatory = $false)]
|
|
[string]$ThemeMode = "System",
|
|
[Parameter(Mandatory = $false)]
|
|
[PSCustomObject]$State
|
|
)
|
|
|
|
# Check if the current .NET runtime supports Window.ThemeMode (requires .NET 9+ / PowerShell 7.5+)
|
|
$themeModeProperty = [System.Windows.Window].GetProperty("ThemeMode")
|
|
if ($null -eq $themeModeProperty) {
|
|
WriteLog "Fluent theme not available. Window.ThemeMode requires PowerShell 7.5+ (.NET 9+). Using default Aero2 theme."
|
|
if ($null -ne $State) {
|
|
$State.Flags.isFluentSupported = $false
|
|
}
|
|
# Still create tooltip styles for non-Fluent mode so Tag-to-ToolTip binding works
|
|
$controlTypes = @(
|
|
[System.Windows.Controls.TextBox],
|
|
[System.Windows.Controls.TextBlock],
|
|
[System.Windows.Controls.CheckBox]
|
|
)
|
|
foreach ($controlType in $controlTypes) {
|
|
$newStyle = New-Object System.Windows.Style($controlType)
|
|
$toolTipBinding = New-Object System.Windows.Data.Binding("Tag")
|
|
$toolTipBinding.RelativeSource = [System.Windows.Data.RelativeSource]::new([System.Windows.Data.RelativeSourceMode]::Self)
|
|
$toolTipSetter = New-Object System.Windows.Setter([System.Windows.FrameworkElement]::ToolTipProperty, $toolTipBinding)
|
|
$newStyle.Setters.Add($toolTipSetter)
|
|
if ($Window.Resources.Contains($controlType)) {
|
|
$Window.Resources.Remove($controlType)
|
|
}
|
|
$Window.Resources.Add($controlType, $newStyle)
|
|
}
|
|
WriteLog "Tooltip styles created for non-Fluent mode."
|
|
return
|
|
}
|
|
|
|
# Mark Fluent as supported in state
|
|
if ($null -ne $State) {
|
|
$State.Flags.isFluentSupported = $true
|
|
}
|
|
|
|
# Resolve the ThemeMode enum value using reflection to avoid compile-time experimental attribute issues
|
|
$themeModeType = [System.Windows.Window].GetProperty("ThemeMode").PropertyType
|
|
$themeModeValue = $null
|
|
switch ($ThemeMode) {
|
|
"Light" { $themeModeValue = $themeModeType::Light }
|
|
"Dark" { $themeModeValue = $themeModeType::Dark }
|
|
"System" { $themeModeValue = $themeModeType::System }
|
|
default { $themeModeValue = $themeModeType::System }
|
|
}
|
|
|
|
# Apply the Fluent theme mode to the window
|
|
$themeModeProperty.SetValue($Window, $themeModeValue)
|
|
WriteLog "Applied Fluent theme: $ThemeMode"
|
|
|
|
# Re-create implicit tooltip styles with BasedOn pointing to the Fluent base style
|
|
# This preserves the Tag-to-ToolTip binding while inheriting Fluent visual styling
|
|
$controlTypes = @(
|
|
[System.Windows.Controls.TextBox],
|
|
[System.Windows.Controls.TextBlock],
|
|
[System.Windows.Controls.CheckBox]
|
|
)
|
|
|
|
foreach ($controlType in $controlTypes) {
|
|
# Get the Fluent base style that was loaded by ThemeMode
|
|
$fluentBaseStyle = $Window.TryFindResource($controlType)
|
|
|
|
# Create a new implicit style with ToolTip binding
|
|
$newStyle = New-Object System.Windows.Style($controlType)
|
|
if ($null -ne $fluentBaseStyle) {
|
|
$newStyle.BasedOn = $fluentBaseStyle
|
|
}
|
|
|
|
# Add the ToolTip setter that binds to the Tag property
|
|
$toolTipBinding = New-Object System.Windows.Data.Binding("Tag")
|
|
$toolTipBinding.RelativeSource = [System.Windows.Data.RelativeSource]::new([System.Windows.Data.RelativeSourceMode]::Self)
|
|
$toolTipSetter = New-Object System.Windows.Setter([System.Windows.FrameworkElement]::ToolTipProperty, $toolTipBinding)
|
|
$newStyle.Setters.Add($toolTipSetter)
|
|
|
|
# Remove any existing implicit style for this type before adding the new one
|
|
if ($Window.Resources.Contains($controlType)) {
|
|
$Window.Resources.Remove($controlType)
|
|
}
|
|
$Window.Resources.Add($controlType, $newStyle)
|
|
}
|
|
|
|
WriteLog "Tooltip styles updated with Fluent base styles."
|
|
}
|
|
|
|
function Initialize-UIControls {
|
|
param([PSCustomObject]$State)
|
|
WriteLog "Initializing UI control references..."
|
|
$window = $State.Window
|
|
# Find all controls ONCE and store them in the state object
|
|
$State.Controls.cmbWindowsRelease = $window.FindName('cmbWindowsRelease')
|
|
$State.Controls.cmbWindowsVersion = $window.FindName('cmbWindowsVersion')
|
|
$State.Controls.txtISOPath = $window.FindName('txtISOPath')
|
|
$State.Controls.rbDownloadESD = $window.FindName('rbDownloadESD')
|
|
$State.Controls.rbProvideISO = $window.FindName('rbProvideISO')
|
|
$State.Controls.isoPathPanel = $window.FindName('isoPathPanel')
|
|
$State.Controls.btnBrowseISO = $window.FindName('btnBrowseISO')
|
|
$State.Controls.cmbWindowsArch = $window.FindName('cmbWindowsArch')
|
|
$State.Controls.cmbWindowsLang = $window.FindName('cmbWindowsLang')
|
|
$State.Controls.WindowsLangStackPanel = $window.FindName('WindowsLangStackPanel')
|
|
$State.Controls.cmbWindowsSKU = $window.FindName('cmbWindowsSKU')
|
|
$State.Controls.cmbMediaType = $window.FindName('cmbMediaType')
|
|
$State.Controls.MediaTypeStackPanel = $window.FindName('MediaTypeStackPanel')
|
|
$State.Controls.featuresPanel = $window.FindName('stackFeaturesContainer')
|
|
$State.Controls.chkDownloadDrivers = $window.FindName('chkDownloadDrivers')
|
|
$State.Controls.cmbMake = $window.FindName('cmbMake')
|
|
$State.Controls.spMakeSection = $window.FindName('spMakeSection')
|
|
$State.Controls.btnGetModels = $window.FindName('btnGetModels')
|
|
$State.Controls.spModelFilterSection = $window.FindName('spModelFilterSection')
|
|
$State.Controls.txtModelFilter = $window.FindName('txtModelFilter')
|
|
$State.Controls.lstDriverModels = $window.FindName('lstDriverModels')
|
|
$State.Controls.spDriverActionButtons = $window.FindName('spDriverActionButtons')
|
|
$State.Controls.btnSaveDriversJson = $window.FindName('btnSaveDriversJson')
|
|
$State.Controls.btnImportDriversJson = $window.FindName('btnImportDriversJson')
|
|
$State.Controls.btnDownloadSelectedDrivers = $window.FindName('btnDownloadSelectedDrivers')
|
|
$State.Controls.btnClearDriverList = $window.FindName('btnClearDriverList')
|
|
$State.Controls.chkInstallOffice = $window.FindName('chkInstallOffice')
|
|
$State.Controls.chkInstallApps = $window.FindName('chkInstallApps')
|
|
$State.Controls.OfficePathStackPanel = $window.FindName('OfficePathStackPanel')
|
|
$State.Controls.OfficePathGrid = $window.FindName('OfficePathGrid')
|
|
$State.Controls.CopyOfficeConfigXMLStackPanel = $window.FindName('CopyOfficeConfigXMLStackPanel')
|
|
$State.Controls.OfficeConfigurationXMLFileStackPanel = $window.FindName('OfficeConfigurationXMLFileStackPanel')
|
|
$State.Controls.OfficeConfigurationXMLFileGrid = $window.FindName('OfficeConfigurationXMLFileGrid')
|
|
$State.Controls.chkCopyOfficeConfigXML = $window.FindName('chkCopyOfficeConfigXML')
|
|
$State.Controls.chkLatestCU = $window.FindName('chkUpdateLatestCU')
|
|
$State.Controls.chkPreviewCU = $window.FindName('chkUpdatePreviewCU')
|
|
$State.Controls.btnCheckUSBDrives = $window.FindName('btnCheckUSBDrives')
|
|
$State.Controls.lstUSBDrives = $window.FindName('lstUSBDrives')
|
|
$State.Controls.chkBuildUSBDriveEnable = $window.FindName('chkBuildUSBDriveEnable')
|
|
$State.Controls.usbSection = $window.FindName('usbDriveSection')
|
|
$State.Controls.chkSelectSpecificUSBDrives = $window.FindName('chkSelectSpecificUSBDrives')
|
|
$State.Controls.usbSelectionPanel = $window.FindName('usbDriveSelectionPanel')
|
|
$State.Controls.chkAllowExternalHardDiskMedia = $window.FindName('chkAllowExternalHardDiskMedia')
|
|
$State.Controls.chkPromptExternalHardDiskMedia = $window.FindName('chkPromptExternalHardDiskMedia')
|
|
$State.Controls.chkCopyAdditionalFFUFiles = $window.FindName('chkCopyAdditionalFFUFiles')
|
|
$State.Controls.additionalFFUPanel = $window.FindName('additionalFFUPanel')
|
|
$State.Controls.lstAdditionalFFUs = $window.FindName('lstAdditionalFFUs')
|
|
$State.Controls.btnRefreshAdditionalFFUs = $window.FindName('btnRefreshAdditionalFFUs')
|
|
$State.Controls.chkInstallWingetApps = $window.FindName('chkInstallWingetApps')
|
|
$State.Controls.wingetPanel = $window.FindName('wingetPanel')
|
|
$State.Controls.btnCheckWingetModule = $window.FindName('btnCheckWingetModule')
|
|
$State.Controls.txtWingetVersion = $window.FindName('txtWingetVersion')
|
|
$State.Controls.txtWingetModuleVersion = $window.FindName('txtWingetModuleVersion')
|
|
$State.Controls.applicationPathPanel = $window.FindName('applicationPathPanel')
|
|
$State.Controls.appListJsonPathPanel = $window.FindName('appListJsonPathPanel')
|
|
$State.Controls.userAppListPathPanel = $window.FindName('userAppListPathPanel')
|
|
$State.Controls.btnBrowseApplicationPath = $window.FindName('btnBrowseApplicationPath')
|
|
$State.Controls.btnBrowseAppListJsonPath = $window.FindName('btnBrowseAppListJsonPath')
|
|
$State.Controls.btnBrowseUserAppListPath = $window.FindName('btnBrowseUserAppListPath')
|
|
$State.Controls.chkBringYourOwnApps = $window.FindName('chkBringYourOwnApps')
|
|
$State.Controls.byoApplicationPanel = $window.FindName('byoApplicationPanel')
|
|
$State.Controls.wingetSearchPanel = $window.FindName('wingetSearchPanel')
|
|
$State.Controls.txtWingetSearch = $window.FindName('txtWingetSearch')
|
|
$State.Controls.btnWingetSearch = $window.FindName('btnWingetSearch')
|
|
$State.Controls.lstWingetResults = $window.FindName('lstWingetResults')
|
|
$State.Controls.btnSaveWingetList = $window.FindName('btnSaveWingetList')
|
|
$State.Controls.btnImportWingetList = $window.FindName('btnImportWingetList')
|
|
$State.Controls.btnClearWingetList = $window.FindName('btnClearWingetList')
|
|
$State.Controls.btnDownloadSelected = $window.FindName('btnDownloadSelected')
|
|
$State.Controls.btnBrowseAppSource = $window.FindName('btnBrowseAppSource')
|
|
$State.Controls.btnBrowseFFUDevPath = $window.FindName('btnBrowseFFUDevPath')
|
|
$State.Controls.btnBrowseFFUCaptureLocation = $window.FindName('btnBrowseFFUCaptureLocation')
|
|
$State.Controls.btnBrowseOfficePath = $window.FindName('btnBrowseOfficePath')
|
|
$State.Controls.btnBrowseDriversFolder = $window.FindName('btnBrowseDriversFolder')
|
|
$State.Controls.btnBrowsePEDriversFolder = $window.FindName('btnBrowsePEDriversFolder')
|
|
$State.Controls.txtAppName = $window.FindName('txtAppName')
|
|
$State.Controls.txtAppCommandLine = $window.FindName('txtAppCommandLine')
|
|
$State.Controls.txtAppArguments = $window.FindName('txtAppArguments')
|
|
$State.Controls.txtAppSource = $window.FindName('txtAppSource')
|
|
$State.Controls.txtAppAdditionalExitCodes = $window.FindName('txtAppAdditionalExitCodes')
|
|
$State.Controls.chkIgnoreExitCodes = $window.FindName('chkIgnoreExitCodes')
|
|
$State.Controls.btnAddApplication = $window.FindName('btnAddApplication')
|
|
$State.Controls.btnSaveBYOApplications = $window.FindName('btnSaveBYOApplications')
|
|
$State.Controls.btnLoadBYOApplications = $window.FindName('btnLoadBYOApplications')
|
|
$State.Controls.btnEditApplication = $window.FindName('btnEditApplication')
|
|
$State.Controls.btnClearBYOApplications = $window.FindName('btnClearBYOApplications')
|
|
$State.Controls.btnRemoveSelectedBYOApps = $window.FindName('btnRemoveSelectedBYOApps')
|
|
$State.Controls.btnCopyBYOApps = $window.FindName('btnCopyBYOApps')
|
|
$State.Controls.lstApplications = $window.FindName('lstApplications')
|
|
$State.Controls.btnMoveTop = $window.FindName('btnMoveTop')
|
|
$State.Controls.btnMoveUp = $window.FindName('btnMoveUp')
|
|
$State.Controls.btnMoveDown = $window.FindName('btnMoveDown')
|
|
$State.Controls.btnMoveBottom = $window.FindName('btnMoveBottom')
|
|
$State.Controls.txtStatus = $window.FindName('txtStatus')
|
|
$State.Controls.pbOverallProgress = $window.FindName('progressBar')
|
|
$State.Controls.txtOverallStatus = $window.FindName('txtStatus')
|
|
$State.Controls.chkEnableVMNetworking = $window.FindName('chkEnableVMNetworking')
|
|
$State.Controls.spVMNetworkingSettings = $window.FindName('spVMNetworkingSettings')
|
|
$State.Controls.cmbVMSwitchName = $window.FindName('cmbVMSwitchName')
|
|
$State.Controls.txtCustomVMSwitchName = $window.FindName('txtCustomVMSwitchName')
|
|
$State.Controls.txtFFUDevPath = $window.FindName('txtFFUDevPath')
|
|
$State.Controls.txtCustomFFUNameTemplate = $window.FindName('txtCustomFFUNameTemplate')
|
|
$State.Controls.txtFFUCaptureLocation = $window.FindName('txtFFUCaptureLocation')
|
|
$State.Controls.txtThreads = $window.FindName('txtThreads')
|
|
$State.Controls.cmbBitsPriority = $window.FindName('cmbBitsPriority')
|
|
$State.Controls.txtMaxUSBDrives = $window.FindName('txtMaxUSBDrives')
|
|
$State.Controls.chkCompactOS = $window.FindName('chkCompactOS')
|
|
$State.Controls.chkOptimize = $window.FindName('chkOptimize')
|
|
$State.Controls.chkAllowVHDXCaching = $window.FindName('chkAllowVHDXCaching')
|
|
$State.Controls.chkCreateDeploymentMedia = $window.FindName('chkCreateDeploymentMedia')
|
|
$State.Controls.chkInjectUnattend = $window.FindName('chkInjectUnattend')
|
|
$State.Controls.rbDeviceNamingNone = $window.FindName('rbDeviceNamingNone')
|
|
$State.Controls.rbDeviceNamingTemplate = $window.FindName('rbDeviceNamingTemplate')
|
|
$State.Controls.rbDeviceNamingPrefixes = $window.FindName('rbDeviceNamingPrefixes')
|
|
$State.Controls.deviceNameTemplatePanel = $window.FindName('deviceNameTemplatePanel')
|
|
$State.Controls.deviceNamePrefixesPanel = $window.FindName('deviceNamePrefixesPanel')
|
|
$State.Controls.txtDeviceNameTemplate = $window.FindName('txtDeviceNameTemplate')
|
|
$State.Controls.txtDeviceNamePrefixesPath = $window.FindName('txtDeviceNamePrefixesPath')
|
|
$State.Controls.btnBrowseDeviceNamePrefixesPath = $window.FindName('btnBrowseDeviceNamePrefixesPath')
|
|
$State.Controls.txtDeviceNamePrefixes = $window.FindName('txtDeviceNamePrefixes')
|
|
$State.Controls.btnSaveDeviceNamePrefixes = $window.FindName('btnSaveDeviceNamePrefixes')
|
|
$State.Controls.chkVerbose = $window.FindName('chkVerbose')
|
|
$State.Controls.chkCopyAutopilot = $window.FindName('chkCopyAutopilot')
|
|
$State.Controls.chkCopyUnattend = $window.FindName('chkCopyUnattend')
|
|
$State.Controls.chkCopyPPKG = $window.FindName('chkCopyPPKG')
|
|
$State.Controls.chkCleanupAppsISO = $window.FindName('chkCleanupAppsISO')
|
|
$State.Controls.chkCleanupDeployISO = $window.FindName('chkCleanupDeployISO')
|
|
$State.Controls.chkCleanupDrivers = $window.FindName('chkCleanupDrivers')
|
|
$State.Controls.chkRemoveFFU = $window.FindName('chkRemoveFFU')
|
|
$State.Controls.chkRemoveDownloadedESD = $window.FindName('chkRemoveDownloadedESD')
|
|
$State.Controls.txtDiskSize = $window.FindName('txtDiskSize')
|
|
$State.Controls.txtMemory = $window.FindName('txtMemory')
|
|
$State.Controls.txtProcessors = $window.FindName('txtProcessors')
|
|
$State.Controls.txtVMLocation = $window.FindName('txtVMLocation')
|
|
$State.Controls.txtVMNamePrefix = $window.FindName('txtVMNamePrefix')
|
|
$State.Controls.cmbLogicalSectorSize = $window.FindName('cmbLogicalSectorSize')
|
|
$State.Controls.txtProductKey = $window.FindName('txtProductKey')
|
|
$State.Controls.txtOfficePath = $window.FindName('txtOfficePath')
|
|
$State.Controls.txtOfficeConfigXMLFilePath = $window.FindName('txtOfficeConfigXMLFilePath')
|
|
$State.Controls.btnBrowseOfficeConfigXMLFile = $window.FindName('btnBrowseOfficeConfigXMLFile')
|
|
$State.Controls.txtDriversFolder = $window.FindName('txtDriversFolder')
|
|
$State.Controls.txtPEDriversFolder = $window.FindName('txtPEDriversFolder')
|
|
$State.Controls.chkCopyPEDrivers = $window.FindName('chkCopyPEDrivers')
|
|
$State.Controls.chkUseDriversAsPEDrivers = $window.FindName('chkUseDriversAsPEDrivers')
|
|
$State.Controls.chkUpdateLatestCU = $window.FindName('chkUpdateLatestCU')
|
|
$State.Controls.chkUpdateLatestNet = $window.FindName('chkUpdateLatestNet')
|
|
$State.Controls.chkUpdateLatestDefender = $window.FindName('chkUpdateLatestDefender')
|
|
$State.Controls.chkUpdateEdge = $window.FindName('chkUpdateEdge')
|
|
$State.Controls.chkUpdateOneDrive = $window.FindName('chkUpdateOneDrive')
|
|
$State.Controls.chkUpdateLatestMSRT = $window.FindName('chkUpdateLatestMSRT')
|
|
$State.Controls.chkUpdatePreviewCU = $window.FindName('chkUpdatePreviewCU')
|
|
$State.Controls.txtApplicationPath = $window.FindName('txtApplicationPath')
|
|
$State.Controls.txtAppListJsonPath = $window.FindName('txtAppListJsonPath')
|
|
$State.Controls.txtUserAppListPath = $window.FindName('txtUserAppListPath')
|
|
$State.Controls.chkInstallDrivers = $window.FindName('chkInstallDrivers')
|
|
$State.Controls.chkCopyDrivers = $window.FindName('chkCopyDrivers')
|
|
$State.Controls.chkCompressDriversToWIM = $window.FindName('chkCompressDriversToWIM')
|
|
$State.Controls.chkRemoveApps = $window.FindName('chkRemoveApps')
|
|
$State.Controls.chkRemoveUpdates = $window.FindName('chkRemoveUpdates')
|
|
$State.Controls.chkUpdateLatestMicrocode = $window.FindName('chkUpdateLatestMicrocode')
|
|
$State.Controls.chkDefineAppsScriptVariables = $window.FindName('chkDefineAppsScriptVariables')
|
|
$State.Controls.appsScriptVariablesPanel = $window.FindName('appsScriptVariablesPanel')
|
|
$State.Controls.txtAppsScriptKey = $window.FindName('txtAppsScriptKey')
|
|
$State.Controls.txtAppsScriptValue = $window.FindName('txtAppsScriptValue')
|
|
$State.Controls.btnAddAppsScriptVariable = $window.FindName('btnAddAppsScriptVariable')
|
|
$State.Controls.lstAppsScriptVariables = $window.FindName('lstAppsScriptVariables')
|
|
$State.Controls.btnRemoveSelectedAppsScriptVariables = $window.FindName('btnRemoveSelectedAppsScriptVariables')
|
|
$State.Controls.btnClearAppsScriptVariables = $window.FindName('btnClearAppsScriptVariables')
|
|
$State.Controls.txtDriversJsonPath = $window.FindName('txtDriversJsonPath')
|
|
$State.Controls.btnBrowseDriversJsonPath = $window.FindName('btnBrowseDriversJsonPath')
|
|
$State.Controls.chkUpdateADK = $window.FindName('chkUpdateADK')
|
|
$State.Controls.btnLoadConfig = $window.FindName('btnLoadConfig')
|
|
$State.Controls.btnRestoreDefaults = $window.FindName('btnRestoreDefaults')
|
|
$State.Controls.btnBuildConfig = $window.FindName('btnBuildConfig')
|
|
|
|
# Home page
|
|
$State.Controls.txtHomeCurrentBuildValue = $window.FindName('txtHomeCurrentBuildValue')
|
|
$State.Controls.txtHomeLatestReleaseValue = $window.FindName('txtHomeLatestReleaseValue')
|
|
$State.Controls.txtHomeReleaseStatusValue = $window.FindName('txtHomeReleaseStatusValue')
|
|
$State.Controls.spHomeReleaseNotesSections = $window.FindName('spHomeReleaseNotesSections')
|
|
$State.Controls.ellipseHomeDiskSpaceStatus = $window.FindName('ellipseHomeDiskSpaceStatus')
|
|
$State.Controls.txtHomeDiskSpaceStatusValue = $window.FindName('txtHomeDiskSpaceStatusValue')
|
|
$State.Controls.ellipseHomeHyperVStatus = $window.FindName('ellipseHomeHyperVStatus')
|
|
$State.Controls.txtHomeHyperVStatusValue = $window.FindName('txtHomeHyperVStatusValue')
|
|
$State.Controls.txtHomeDiscussionsStatusValue = $window.FindName('txtHomeDiscussionsStatusValue')
|
|
$State.Controls.tbDiscussion1 = $window.FindName('tbDiscussion1')
|
|
$State.Controls.linkDiscussion1 = $window.FindName('linkDiscussion1')
|
|
$State.Controls.runDiscussion1 = $window.FindName('runDiscussion1')
|
|
$State.Controls.tbDiscussion2 = $window.FindName('tbDiscussion2')
|
|
$State.Controls.linkDiscussion2 = $window.FindName('linkDiscussion2')
|
|
$State.Controls.runDiscussion2 = $window.FindName('runDiscussion2')
|
|
$State.Controls.tbDiscussion3 = $window.FindName('tbDiscussion3')
|
|
$State.Controls.linkDiscussion3 = $window.FindName('linkDiscussion3')
|
|
$State.Controls.runDiscussion3 = $window.FindName('runDiscussion3')
|
|
$State.Controls.tbDiscussion4 = $window.FindName('tbDiscussion4')
|
|
$State.Controls.linkDiscussion4 = $window.FindName('linkDiscussion4')
|
|
$State.Controls.runDiscussion4 = $window.FindName('runDiscussion4')
|
|
$State.Controls.tbDiscussion5 = $window.FindName('tbDiscussion5')
|
|
$State.Controls.linkDiscussion5 = $window.FindName('linkDiscussion5')
|
|
$State.Controls.runDiscussion5 = $window.FindName('runDiscussion5')
|
|
$State.Controls.tbDiscussionsLink = $window.FindName('tbDiscussionsLink')
|
|
$State.Controls.linkDiscussions = $window.FindName('linkDiscussions')
|
|
|
|
# Settings page
|
|
$State.Controls.cmbThemeMode = $window.FindName('cmbThemeMode')
|
|
|
|
# Shared page shell
|
|
$State.Controls.txtPageTitle = $window.FindName('txtPageTitle')
|
|
|
|
# Navigation controls
|
|
$State.Controls.lstNavigation = $window.FindName('lstNavigation')
|
|
$State.Controls.lstNavSettings = $window.FindName('lstNavSettings')
|
|
$State.Controls.lstLogOutput = $window.FindName('lstLogOutput')
|
|
|
|
# Content pages (for navigation visibility toggling)
|
|
$State.Controls.navigationPages = @(
|
|
$window.FindName('pageHome'),
|
|
$window.FindName('pageHyperV'),
|
|
$window.FindName('pageWindows'),
|
|
$window.FindName('pageUpdates'),
|
|
$window.FindName('pageApplications'),
|
|
$window.FindName('pageOffice'),
|
|
$window.FindName('pageDrivers'),
|
|
$window.FindName('pageBuild'),
|
|
$window.FindName('pageMonitor')
|
|
)
|
|
$State.Controls.pageSettings = $window.FindName('pageSettings')
|
|
|
|
# Initialize and bind the log data collection
|
|
$State.Data.logData = New-Object System.Collections.ObjectModel.ObservableCollection[string]
|
|
$State.Controls.lstLogOutput.ItemsSource = $State.Data.logData
|
|
}
|
|
|
|
function Initialize-VMSwitchData {
|
|
param([PSCustomObject]$State)
|
|
|
|
WriteLog "Initializing VM Switch data..."
|
|
|
|
# Hyper-V Settings: Populate VM Switch ComboBox
|
|
$vmSwitchData = Get-VMSwitchData
|
|
$State.Data.vmSwitchMap = $vmSwitchData.SwitchMap
|
|
$State.Controls.cmbVMSwitchName.Items.Clear()
|
|
foreach ($switchName in $vmSwitchData.SwitchNames) {
|
|
$State.Controls.cmbVMSwitchName.Items.Add($switchName) | Out-Null
|
|
}
|
|
$State.Controls.cmbVMSwitchName.Items.Add('Other') | Out-Null
|
|
if ($State.Controls.cmbVMSwitchName.Items.Count -gt 1) {
|
|
$State.Controls.cmbVMSwitchName.SelectedIndex = 0
|
|
$State.Controls.txtCustomVMSwitchName.Visibility = 'Collapsed'
|
|
}
|
|
else {
|
|
$State.Controls.cmbVMSwitchName.SelectedItem = 'Other'
|
|
$State.Controls.txtCustomVMSwitchName.Visibility = 'Visible'
|
|
}
|
|
}
|
|
|
|
function Initialize-UIDefaults {
|
|
param([PSCustomObject]$State)
|
|
WriteLog "Initializing UI defaults..."
|
|
|
|
# Get default values from helper functions
|
|
$State.Defaults.windowsSettingsDefaults = Get-WindowsSettingsDefaults
|
|
$State.Defaults.generalDefaults = Get-GeneralDefaults -FFUDevelopmentPath $State.FFUDevelopmentPath
|
|
|
|
# Build tab defaults from General Defaults
|
|
$State.Controls.txtFFUDevPath.Text = $State.FFUDevelopmentPath
|
|
$State.Controls.txtCustomFFUNameTemplate.Text = $State.Defaults.generalDefaults.CustomFFUNameTemplate
|
|
$State.Controls.txtFFUCaptureLocation.Text = $State.Defaults.generalDefaults.FFUCaptureLocation
|
|
$State.Controls.txtThreads.Text = $State.Defaults.generalDefaults.Threads
|
|
$State.Controls.cmbBitsPriority.SelectedItem = $State.Defaults.generalDefaults.BitsPriority
|
|
$State.Controls.txtMaxUSBDrives.Text = $State.Defaults.generalDefaults.MaxUSBDrives
|
|
$State.Controls.chkBuildUSBDriveEnable.IsChecked = $State.Defaults.generalDefaults.BuildUSBDriveEnable
|
|
$State.Controls.chkCompactOS.IsChecked = $State.Defaults.generalDefaults.CompactOS
|
|
$State.Controls.chkUpdateADK.IsChecked = $State.Defaults.generalDefaults.UpdateADK
|
|
$State.Controls.chkOptimize.IsChecked = $State.Defaults.generalDefaults.Optimize
|
|
$State.Controls.chkAllowVHDXCaching.IsChecked = $State.Defaults.generalDefaults.AllowVHDXCaching
|
|
$State.Controls.chkInjectUnattend.IsChecked = $State.Defaults.generalDefaults.InjectUnattend
|
|
$State.Controls.chkCreateDeploymentMedia.IsChecked = $State.Defaults.generalDefaults.CreateDeploymentMedia
|
|
$State.Controls.chkAllowExternalHardDiskMedia.IsChecked = $State.Defaults.generalDefaults.AllowExternalHardDiskMedia
|
|
$State.Controls.chkPromptExternalHardDiskMedia.IsChecked = $State.Defaults.generalDefaults.PromptExternalHardDiskMedia
|
|
$State.Controls.chkSelectSpecificUSBDrives.IsChecked = $State.Defaults.generalDefaults.SelectSpecificUSBDrives
|
|
$State.Controls.chkCopyAutopilot.IsChecked = $State.Defaults.generalDefaults.CopyAutopilot
|
|
$State.Controls.chkCopyUnattend.IsChecked = $State.Defaults.generalDefaults.CopyUnattend
|
|
$State.Controls.chkCopyPPKG.IsChecked = $State.Defaults.generalDefaults.CopyPPKG
|
|
Set-DeviceNamingMode -State $State -Mode $State.Defaults.generalDefaults.DeviceNamingMode
|
|
$State.Controls.txtDeviceNameTemplate.Text = $State.Defaults.generalDefaults.DeviceNameTemplate
|
|
$State.Controls.txtDeviceNamePrefixesPath.Text = $State.Defaults.generalDefaults.DeviceNamePrefixesPath
|
|
$State.Controls.txtDeviceNamePrefixes.Text = ($State.Defaults.generalDefaults.DeviceNamePrefixes -join [System.Environment]::NewLine)
|
|
Import-DeviceNamePrefixesFromConfiguredPath -State $State
|
|
Update-DeviceNamingControls -State $State
|
|
$State.Controls.chkCleanupAppsISO.IsChecked = $State.Defaults.generalDefaults.CleanupAppsISO
|
|
$State.Controls.chkCleanupDeployISO.IsChecked = $State.Defaults.generalDefaults.CleanupDeployISO
|
|
$State.Controls.chkCleanupDrivers.IsChecked = $State.Defaults.generalDefaults.CleanupDrivers
|
|
$State.Controls.chkRemoveFFU.IsChecked = $State.Defaults.generalDefaults.RemoveFFU
|
|
$State.Controls.chkRemoveApps.IsChecked = $State.Defaults.generalDefaults.RemoveApps
|
|
$State.Controls.chkRemoveUpdates.IsChecked = $State.Defaults.generalDefaults.RemoveUpdates
|
|
$State.Controls.chkRemoveDownloadedESD.IsChecked = $State.Defaults.generalDefaults.RemoveDownloadedESD
|
|
$State.Controls.chkVerbose.IsChecked = $State.Defaults.generalDefaults.Verbose
|
|
$State.Controls.usbSelectionPanel.Visibility = if ($State.Controls.chkSelectSpecificUSBDrives.IsChecked) { 'Visible' } else { 'Collapsed' }
|
|
$State.Controls.chkSelectSpecificUSBDrives.IsEnabled = $State.Controls.chkBuildUSBDriveEnable.IsChecked
|
|
$State.Controls.chkPromptExternalHardDiskMedia.IsEnabled = $State.Controls.chkAllowExternalHardDiskMedia.IsChecked
|
|
$State.Controls.chkCopyAdditionalFFUFiles.IsChecked = $State.Defaults.generalDefaults.CopyAdditionalFFUFiles
|
|
$State.Controls.additionalFFUPanel.Visibility = if ($State.Controls.chkCopyAdditionalFFUFiles.IsChecked) { 'Visible' } else { 'Collapsed' }
|
|
Update-BitsPrioritySetting -State $State
|
|
|
|
# Hyper-V Settings defaults from General Defaults
|
|
$State.Controls.chkEnableVMNetworking.IsChecked = $State.Defaults.generalDefaults.EnableVMNetworking
|
|
Initialize-VMSwitchData -State $State
|
|
$State.Controls.spVMNetworkingSettings.IsEnabled = $true -eq $State.Controls.chkEnableVMNetworking.IsChecked
|
|
$State.Controls.txtDiskSize.Text = $State.Defaults.generalDefaults.DiskSizeGB
|
|
$State.Controls.txtMemory.Text = $State.Defaults.generalDefaults.MemoryGB
|
|
$State.Controls.txtProcessors.Text = $State.Defaults.generalDefaults.Processors
|
|
$State.Controls.txtVMLocation.Text = $State.Defaults.generalDefaults.VMLocation
|
|
$State.Controls.txtVMNamePrefix.Text = $State.Defaults.generalDefaults.VMNamePrefix
|
|
$State.Controls.cmbLogicalSectorSize.SelectedItem = ($State.Controls.cmbLogicalSectorSize.Items | Where-Object { $_.Content -eq $State.Defaults.generalDefaults.LogicalSectorSize.ToString() })
|
|
|
|
# Populate Windows Release, Version, and SKU comboboxes
|
|
# Initialize Windows settings combos based on media source mode
|
|
$initIsoPath = $State.Defaults.windowsSettingsDefaults.DefaultISOPath
|
|
if ($null -ne $State.Controls.rbProvideISO -and -not $State.Controls.rbProvideISO.IsChecked) {
|
|
$initIsoPath = ''
|
|
}
|
|
Get-WindowsSettingsCombos -isoPath $initIsoPath -State $State
|
|
|
|
# Windows Settings tab defaults
|
|
$State.Controls.cmbWindowsLang.ItemsSource = $State.Defaults.windowsSettingsDefaults.AllowedLanguages
|
|
$State.Controls.cmbWindowsLang.SelectedItem = $State.Defaults.windowsSettingsDefaults.DefaultWindowsLang
|
|
$State.Controls.cmbMediaType.ItemsSource = $State.Defaults.windowsSettingsDefaults.AllowedMediaTypes
|
|
$State.Controls.cmbMediaType.SelectedItem = $State.Defaults.windowsSettingsDefaults.DefaultMediaType
|
|
$State.Controls.txtProductKey.Text = $State.Defaults.windowsSettingsDefaults.DefaultProductKey
|
|
|
|
# Updates tab defaults from General Defaults
|
|
$State.Controls.chkUpdateLatestCU.IsChecked = $State.Defaults.generalDefaults.UpdateLatestCU
|
|
$State.Controls.chkUpdateLatestNet.IsChecked = $State.Defaults.generalDefaults.UpdateLatestNet
|
|
$State.Controls.chkUpdateLatestDefender.IsChecked = $State.Defaults.generalDefaults.UpdateLatestDefender
|
|
$State.Controls.chkUpdateEdge.IsChecked = $State.Defaults.generalDefaults.UpdateEdge
|
|
$State.Controls.chkUpdateOneDrive.IsChecked = $State.Defaults.generalDefaults.UpdateOneDrive
|
|
$State.Controls.chkUpdateLatestMSRT.IsChecked = $State.Defaults.generalDefaults.UpdateLatestMSRT
|
|
$State.Controls.chkUpdateLatestMicrocode.IsChecked = $State.Defaults.generalDefaults.UpdateLatestMicrocode
|
|
$State.Controls.chkUpdatePreviewCU.IsChecked = $State.Defaults.generalDefaults.UpdatePreviewCU
|
|
# Set initial state for CU checkbox interplay
|
|
$State.Controls.chkPreviewCU.IsEnabled = -not $State.Controls.chkLatestCU.IsChecked
|
|
$State.Controls.chkLatestCU.IsEnabled = -not $State.Controls.chkPreviewCU.IsChecked
|
|
|
|
# Applications tab defaults from General Defaults
|
|
$State.Controls.chkInstallApps.IsChecked = $State.Defaults.generalDefaults.InstallApps
|
|
$State.Controls.txtApplicationPath.Text = $State.Defaults.generalDefaults.ApplicationPath
|
|
$State.Controls.txtAppListJsonPath.Text = $State.Defaults.generalDefaults.AppListJsonPath
|
|
$State.Controls.txtUserAppListPath.Text = $State.Defaults.generalDefaults.UserAppListPath
|
|
$State.Controls.chkInstallWingetApps.IsChecked = $State.Defaults.generalDefaults.InstallWingetApps
|
|
$State.Controls.chkBringYourOwnApps.IsChecked = $State.Defaults.generalDefaults.BringYourOwnApps
|
|
|
|
# M365 Apps/Office tab defaults from General Defaults
|
|
$State.Controls.chkInstallOffice.IsChecked = $State.Defaults.generalDefaults.InstallOffice
|
|
$State.Controls.txtOfficePath.Text = $State.Defaults.generalDefaults.OfficePath
|
|
$State.Controls.chkCopyOfficeConfigXML.IsChecked = $State.Defaults.generalDefaults.CopyOfficeConfigXML
|
|
$State.Controls.txtOfficeConfigXMLFilePath.Text = $State.Defaults.generalDefaults.OfficeConfigXMLFilePath
|
|
|
|
# Drivers tab defaults from General Defaults
|
|
$State.Controls.txtDriversFolder.Text = $State.Defaults.generalDefaults.DriversFolder
|
|
$State.Controls.txtPEDriversFolder.Text = $State.Defaults.generalDefaults.PEDriversFolder
|
|
$State.Controls.txtDriversJsonPath.Text = $State.Defaults.generalDefaults.DriversJsonPath
|
|
$State.Controls.chkDownloadDrivers.IsChecked = $State.Defaults.generalDefaults.DownloadDrivers
|
|
$State.Controls.chkInstallDrivers.IsChecked = $State.Defaults.generalDefaults.InstallDrivers
|
|
$State.Controls.chkCopyDrivers.IsChecked = $State.Defaults.generalDefaults.CopyDrivers
|
|
$State.Controls.chkCopyPEDrivers.IsChecked = $State.Defaults.generalDefaults.CopyPEDrivers
|
|
$State.Controls.chkUseDriversAsPEDrivers.IsChecked = $State.Defaults.generalDefaults.UseDriversAsPEDrivers
|
|
$State.Controls.chkCompressDriversToWIM.IsChecked = $State.Defaults.generalDefaults.CompressDownloadedDriversToWim
|
|
|
|
# Drivers tab UI logic
|
|
$makeList = @('Microsoft', 'Dell', 'HP', 'Lenovo')
|
|
if ($null -ne $State.Controls.cmbMake) {
|
|
# Clear existing items to prevent duplication on re-initialization (e.g., after Restore Defaults)
|
|
$State.Controls.cmbMake.Items.Clear()
|
|
foreach ($m in $makeList) {
|
|
[void]$State.Controls.cmbMake.Items.Add($m)
|
|
}
|
|
if ($State.Controls.cmbMake.Items.Count -gt 0) {
|
|
$State.Controls.cmbMake.SelectedIndex = 0
|
|
}
|
|
}
|
|
Update-DriverDownloadPanelVisibility -State $State
|
|
|
|
# Set initial state for driver checkbox interplay
|
|
Update-DriverCheckboxStates -State $State
|
|
|
|
# Set initial state for InstallApps checkbox based on updates
|
|
Update-InstallAppsState -State $State
|
|
|
|
# Set default theme mode and disable if Fluent is not supported
|
|
if ($null -ne $State.Controls.cmbThemeMode) {
|
|
$State.Controls.cmbThemeMode.SelectedItem = "System"
|
|
if (-not $State.Flags.isFluentSupported) {
|
|
$State.Controls.cmbThemeMode.IsEnabled = $false
|
|
$State.Controls.cmbThemeMode.Tag = "Fluent theme requires PowerShell 7.5+ (.NET 9+). Best experience on PowerShell 7.6+ (.NET 10)."
|
|
}
|
|
}
|
|
|
|
# Set default navigation selection to Home and initialize the shared page title
|
|
if ($null -ne $State.Controls.lstNavigation) {
|
|
$State.Controls.lstNavigation.SelectedIndex = 0
|
|
|
|
# Keep the shell header aligned with the selected navigation item on first render
|
|
if ($null -ne $State.Controls.txtPageTitle) {
|
|
$selectedNavigationItem = $State.Controls.lstNavigation.SelectedItem
|
|
if ($null -ne $selectedNavigationItem -and -not [string]::IsNullOrWhiteSpace([string]$selectedNavigationItem.Tag)) {
|
|
$State.Controls.txtPageTitle.Text = [string]$selectedNavigationItem.Tag
|
|
}
|
|
else {
|
|
$State.Controls.txtPageTitle.Text = 'Home'
|
|
}
|
|
}
|
|
}
|
|
|
|
# Set initial state for Office panel visibility
|
|
Update-OfficePanelVisibility -State $State
|
|
|
|
# Set initial state for Application panel visibility
|
|
Update-ApplicationPanelVisibility -State $State
|
|
|
|
# Set initial state for BYO Apps copy button
|
|
Update-CopyButtonState -State $State
|
|
|
|
# Apply accent color to primary action button only (per Windows design guidance)
|
|
if ($State.Flags.isFluentSupported) {
|
|
try {
|
|
$State.Controls.btnRun = $State.Window.FindName('btnRun')
|
|
if ($null -ne $State.Controls.btnRun) {
|
|
# Use SetResourceReference for live accent color updates when user changes Windows theme
|
|
$State.Controls.btnRun.SetResourceReference(
|
|
[System.Windows.Controls.Control]::BackgroundProperty,
|
|
[System.Windows.SystemColors]::AccentColorBrushKey
|
|
)
|
|
$State.Controls.btnRun.Foreground = [System.Windows.Media.Brushes]::White
|
|
}
|
|
}
|
|
catch {
|
|
WriteLog "Could not apply accent color to Build FFU button: $($_.Exception.Message)"
|
|
}
|
|
}
|
|
}
|
|
|
|
function Initialize-DynamicUIElements {
|
|
param([PSCustomObject]$State)
|
|
WriteLog "Initializing dynamic UI elements (Grids, Columns)..."
|
|
|
|
# Get the Fluent base style for ListViewItem in GridView mode
|
|
# Must use GridViewItemContainerStyleKey (not the generic ListViewItem type key) because the
|
|
# generic Fluent ListViewItem style has a template without GridViewRowPresenter, which breaks
|
|
# column-based rendering and causes items to display their ToString() representation.
|
|
$listViewItemBaseStyle = $State.Window.TryFindResource([System.Windows.Controls.GridView]::GridViewItemContainerStyleKey)
|
|
|
|
# Driver Models ListView setup
|
|
# Set ListViewItem style to stretch content horizontally so cell templates fill the cell
|
|
$itemStyleDriverModels = New-Object System.Windows.Style([System.Windows.Controls.ListViewItem])
|
|
if ($null -ne $listViewItemBaseStyle) { $itemStyleDriverModels.BasedOn = $listViewItemBaseStyle }
|
|
$itemStyleDriverModels.Setters.Add((New-Object System.Windows.Setter([System.Windows.Controls.ListViewItem]::HorizontalContentAlignmentProperty, [System.Windows.HorizontalAlignment]::Stretch)))
|
|
$State.Controls.lstDriverModels.ItemContainerStyle = $itemStyleDriverModels
|
|
|
|
$driverModelsGridView = New-Object System.Windows.Controls.GridView
|
|
$State.Controls.lstDriverModels.View = $driverModelsGridView # Assign GridView to ListView first
|
|
|
|
# Add the selectable column and scope header select-all to visible filtered rows.
|
|
Add-SelectableGridViewColumn -ListView $State.Controls.lstDriverModels -State $State -HeaderCheckBoxKeyName "chkSelectAllDriverModels" -ColumnWidth 70 -HeaderSelectionAffectsVisibleItemsOnly
|
|
|
|
# Add other sortable columns with left-aligned headers
|
|
Add-SortableColumn -gridView $driverModelsGridView -header "Make" -binding "Make" -width 100 -headerHorizontalAlignment Left
|
|
Add-SortableColumn -gridView $driverModelsGridView -header "Model" -binding "Model" -width 200 -headerHorizontalAlignment Left
|
|
Add-SortableColumn -gridView $driverModelsGridView -header "Status" -binding "DownloadStatus" -width 150 -headerHorizontalAlignment Left
|
|
$State.Controls.lstDriverModels.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
|
|
}
|
|
}
|
|
)
|
|
|
|
# Keep driver model columns sized to the current visible content.
|
|
Enable-ListViewColumnAutoResize -ListView $State.Controls.lstDriverModels -FixedColumnIndexes @(0)
|
|
|
|
# Winget Search ListView setup
|
|
$wingetGridView = New-Object System.Windows.Controls.GridView
|
|
$State.Controls.lstWingetResults.View = $wingetGridView # Assign GridView to ListView first
|
|
|
|
# Set ListViewItem style to stretch content horizontally so cell templates fill the cell
|
|
$itemStyleWingetResults = New-Object System.Windows.Style([System.Windows.Controls.ListViewItem])
|
|
if ($null -ne $listViewItemBaseStyle) { $itemStyleWingetResults.BasedOn = $listViewItemBaseStyle }
|
|
$itemStyleWingetResults.Setters.Add((New-Object System.Windows.Setter([System.Windows.Controls.ListViewItem]::HorizontalContentAlignmentProperty, [System.Windows.HorizontalAlignment]::Stretch)))
|
|
$State.Controls.lstWingetResults.ItemContainerStyle = $itemStyleWingetResults
|
|
|
|
# Add the selectable column using the new function
|
|
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
|
|
Add-SortableColumn -gridView $wingetGridView -header "Id" -binding "Id" -width 200 -headerHorizontalAlignment Left
|
|
Add-SortableColumn -gridView $wingetGridView -header "Version" -binding "Version" -width 100 -headerHorizontalAlignment Left
|
|
Add-SortableColumn -gridView $wingetGridView -header "Source" -binding "Source" -width 100 -headerHorizontalAlignment Left
|
|
|
|
# --- START: Add Architecture Column ---
|
|
$archColumn = New-Object System.Windows.Controls.GridViewColumn
|
|
$archHeader = New-Object System.Windows.Controls.GridViewColumnHeader
|
|
$archHeader.Tag = "Architecture" # For sorting
|
|
$archHeader.HorizontalContentAlignment = [System.Windows.HorizontalAlignment]::Left
|
|
|
|
# Create header content with correct padding to match other columns
|
|
$commonPaddingForHeader = New-Object System.Windows.Thickness(5, 2, 5, 2)
|
|
$headerTextElementFactory = New-Object System.Windows.FrameworkElementFactory([System.Windows.Controls.TextBlock])
|
|
$headerTextElementFactory.SetValue([System.Windows.Controls.TextBlock]::TextProperty, "Architecture")
|
|
$headerTextBlockPadding = New-Object System.Windows.Thickness($commonPaddingForHeader.Left, $commonPaddingForHeader.Top, $commonPaddingForHeader.Right, $commonPaddingForHeader.Bottom)
|
|
$headerTextElementFactory.SetValue([System.Windows.Controls.TextBlock]::PaddingProperty, $headerTextBlockPadding)
|
|
$headerTextElementFactory.SetValue([System.Windows.FrameworkElement]::VerticalAlignmentProperty, [System.Windows.VerticalAlignment]::Center)
|
|
|
|
$headerDataTemplate = New-Object System.Windows.DataTemplate
|
|
$headerDataTemplate.VisualTree = $headerTextElementFactory
|
|
$archHeader.ContentTemplate = $headerDataTemplate
|
|
|
|
$archColumn.Header = $archHeader
|
|
$archColumn.Width = 120
|
|
|
|
# Create the CellTemplate with a ComboBox
|
|
$archCellTemplate = New-Object System.Windows.DataTemplate
|
|
$comboBoxFactory = New-Object System.Windows.FrameworkElementFactory([System.Windows.Controls.ComboBox])
|
|
|
|
# The ItemsSource for the ComboBox
|
|
$availableArchitectures = @('x86', 'x64', 'arm64', 'x86 x64', 'NA')
|
|
$comboBoxFactory.SetValue([System.Windows.Controls.ItemsControl]::ItemsSourceProperty, $availableArchitectures)
|
|
|
|
# Bind the text property to the 'Architecture' property of the data item.
|
|
# This ensures the initial value is displayed correctly.
|
|
$binding = New-Object System.Windows.Data.Binding("Architecture")
|
|
$binding.Mode = [System.Windows.Data.BindingMode]::TwoWay
|
|
$comboBoxFactory.SetBinding([System.Windows.Controls.ComboBox]::TextProperty, $binding)
|
|
|
|
# Create a style to disable the ComboBox for 'msstore' source, inheriting the Fluent base style
|
|
$comboBoxStyle = New-Object System.Windows.Style
|
|
$comboBoxStyle.TargetType = [System.Windows.Controls.ComboBox]
|
|
$comboBoxBaseStyle = $State.Window.TryFindResource([System.Windows.Controls.ComboBox])
|
|
if ($null -ne $comboBoxBaseStyle) { $comboBoxStyle.BasedOn = $comboBoxBaseStyle }
|
|
|
|
$dataTrigger = New-Object System.Windows.DataTrigger
|
|
$dataTrigger.Binding = New-Object System.Windows.Data.Binding("Source")
|
|
$dataTrigger.Value = "msstore"
|
|
$dataTrigger.Setters.Add((New-Object System.Windows.Setter([System.Windows.Controls.ComboBox]::IsEnabledProperty, $false)))
|
|
|
|
$comboBoxStyle.Triggers.Add($dataTrigger)
|
|
$comboBoxFactory.SetValue([System.Windows.FrameworkElement]::StyleProperty, $comboBoxStyle)
|
|
|
|
$archCellTemplate.VisualTree = $comboBoxFactory
|
|
$archColumn.CellTemplate = $archCellTemplate
|
|
$wingetGridView.Columns.Add($archColumn)
|
|
# --- END: Add Architecture Column ---
|
|
|
|
# --- START: Add Additional Exit Codes Column ---
|
|
$exitCodesColumn = New-Object System.Windows.Controls.GridViewColumn
|
|
$exitCodesHeader = New-Object System.Windows.Controls.GridViewColumnHeader
|
|
$exitCodesHeader.Tag = "AdditionalExitCodes"
|
|
$exitCodesHeader.HorizontalContentAlignment = [System.Windows.HorizontalAlignment]::Left
|
|
|
|
$exitHeaderTextFactory = New-Object System.Windows.FrameworkElementFactory([System.Windows.Controls.TextBlock])
|
|
$exitHeaderTextFactory.SetValue([System.Windows.Controls.TextBlock]::TextProperty, "Additional Exit Codes")
|
|
$exitHeaderTextFactory.SetValue([System.Windows.Controls.TextBlock]::PaddingProperty, (New-Object System.Windows.Thickness(5, 2, 5, 2)))
|
|
$exitHeaderTextFactory.SetValue([System.Windows.FrameworkElement]::VerticalAlignmentProperty, [System.Windows.VerticalAlignment]::Center)
|
|
|
|
$exitHeaderTemplate = New-Object System.Windows.DataTemplate
|
|
$exitHeaderTemplate.VisualTree = $exitHeaderTextFactory
|
|
$exitCodesHeader.ContentTemplate = $exitHeaderTemplate
|
|
|
|
$exitCodesColumn.Header = $exitCodesHeader
|
|
$exitCodesColumn.Width = 140
|
|
|
|
$exitCodesCellTemplate = New-Object System.Windows.DataTemplate
|
|
$exitCodesTextBoxFactory = New-Object System.Windows.FrameworkElementFactory([System.Windows.Controls.TextBox])
|
|
$exitBinding = New-Object System.Windows.Data.Binding("AdditionalExitCodes")
|
|
$exitBinding.Mode = [System.Windows.Data.BindingMode]::TwoWay
|
|
$exitCodesTextBoxFactory.SetBinding([System.Windows.Controls.TextBox]::TextProperty, $exitBinding)
|
|
$exitCodesCellTemplate.VisualTree = $exitCodesTextBoxFactory
|
|
$exitCodesColumn.CellTemplate = $exitCodesCellTemplate
|
|
$wingetGridView.Columns.Add($exitCodesColumn)
|
|
# --- END: Add Additional Exit Codes Column ---
|
|
|
|
# --- START: Add Ignore Non-Zero Exit Codes Column ---
|
|
$ignoreColumn = New-Object System.Windows.Controls.GridViewColumn
|
|
$ignoreHeader = New-Object System.Windows.Controls.GridViewColumnHeader
|
|
$ignoreHeader.Tag = "IgnoreNonZeroExitCodes"
|
|
$ignoreHeader.HorizontalContentAlignment = [System.Windows.HorizontalAlignment]::Left
|
|
|
|
$ignoreHeaderTextFactory = New-Object System.Windows.FrameworkElementFactory([System.Windows.Controls.TextBlock])
|
|
$ignoreHeaderTextFactory.SetValue([System.Windows.Controls.TextBlock]::TextProperty, "Ignore Exit Codes")
|
|
$ignoreHeaderTextFactory.SetValue([System.Windows.Controls.TextBlock]::PaddingProperty, (New-Object System.Windows.Thickness(5, 2, 5, 2)))
|
|
$ignoreHeaderTextFactory.SetValue([System.Windows.FrameworkElement]::VerticalAlignmentProperty, [System.Windows.VerticalAlignment]::Center)
|
|
|
|
$ignoreHeaderTemplate = New-Object System.Windows.DataTemplate
|
|
$ignoreHeaderTemplate.VisualTree = $ignoreHeaderTextFactory
|
|
$ignoreHeader.ContentTemplate = $ignoreHeaderTemplate
|
|
|
|
$ignoreColumn.Header = $ignoreHeader
|
|
$ignoreColumn.Width = 140
|
|
|
|
$ignoreCellTemplate = New-Object System.Windows.DataTemplate
|
|
|
|
# Center the checkbox in the cell
|
|
$ignoreCellGridFactory = New-Object System.Windows.FrameworkElementFactory([System.Windows.Controls.Grid])
|
|
$ignoreCellGridFactory.SetValue([System.Windows.FrameworkElement]::HorizontalAlignmentProperty, [System.Windows.HorizontalAlignment]::Stretch)
|
|
$ignoreCellGridFactory.SetValue([System.Windows.FrameworkElement]::VerticalAlignmentProperty, [System.Windows.VerticalAlignment]::Stretch)
|
|
|
|
$ignoreCheckFactory = New-Object System.Windows.FrameworkElementFactory([System.Windows.Controls.CheckBox])
|
|
$ignoreCheckFactory.SetValue([System.Windows.FrameworkElement]::HorizontalAlignmentProperty, [System.Windows.HorizontalAlignment]::Center)
|
|
$ignoreCheckFactory.SetValue([System.Windows.FrameworkElement]::VerticalAlignmentProperty, [System.Windows.VerticalAlignment]::Center)
|
|
|
|
$ignoreBinding = New-Object System.Windows.Data.Binding("IgnoreNonZeroExitCodes")
|
|
$ignoreBinding.Mode = [System.Windows.Data.BindingMode]::TwoWay
|
|
$ignoreCheckFactory.SetBinding([System.Windows.Controls.Primitives.ToggleButton]::IsCheckedProperty, $ignoreBinding)
|
|
|
|
# Build the visual tree: Grid -> CheckBox
|
|
$ignoreCellGridFactory.AppendChild($ignoreCheckFactory)
|
|
$ignoreCellTemplate.VisualTree = $ignoreCellGridFactory
|
|
|
|
$ignoreColumn.CellTemplate = $ignoreCellTemplate
|
|
$wingetGridView.Columns.Add($ignoreColumn)
|
|
# --- END: Add Ignore Non-Zero Exit Codes Column ---
|
|
|
|
Add-SortableColumn -gridView $wingetGridView -header "Download Status" -binding "DownloadStatus" -width 150 -headerHorizontalAlignment Left
|
|
$State.Controls.lstWingetResults.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
|
|
}
|
|
}
|
|
)
|
|
|
|
# Keep Winget result columns sized to the current visible content.
|
|
Enable-ListViewColumnAutoResize -ListView $State.Controls.lstWingetResults -FixedColumnIndexes @(0)
|
|
|
|
# BYO Applications ListView setup
|
|
$byoAppsGridView = New-Object System.Windows.Controls.GridView
|
|
$State.Controls.lstApplications.View = $byoAppsGridView
|
|
|
|
# Set ListViewItem style to stretch content horizontally
|
|
$itemStyleBYOApps = New-Object System.Windows.Style([System.Windows.Controls.ListViewItem])
|
|
if ($null -ne $listViewItemBaseStyle) { $itemStyleBYOApps.BasedOn = $listViewItemBaseStyle }
|
|
$itemStyleBYOApps.Setters.Add((New-Object System.Windows.Setter([System.Windows.Controls.ListViewItem]::HorizontalContentAlignmentProperty, [System.Windows.HorizontalAlignment]::Stretch)))
|
|
$State.Controls.lstApplications.ItemContainerStyle = $itemStyleBYOApps
|
|
|
|
# Add the selectable column
|
|
Add-SelectableGridViewColumn -ListView $State.Controls.lstApplications -State $State -HeaderCheckBoxKeyName "chkSelectAllBYOApps" -ColumnWidth 60
|
|
|
|
# Add other sortable columns
|
|
Add-SortableColumn -gridView $byoAppsGridView -header "Priority" -binding "Priority" -width 60 -headerHorizontalAlignment Left
|
|
Add-SortableColumn -gridView $byoAppsGridView -header "Name" -binding "Name" -width 150 -headerHorizontalAlignment Left
|
|
Add-SortableColumn -gridView $byoAppsGridView -header "Command Line" -binding "CommandLine" -width 200 -headerHorizontalAlignment Left
|
|
Add-SortableColumn -gridView $byoAppsGridView -header "Arguments" -binding "Arguments" -width 200 -headerHorizontalAlignment Left
|
|
Add-SortableColumn -gridView $byoAppsGridView -header "Source" -binding "Source" -width 150 -headerHorizontalAlignment Left
|
|
Add-SortableColumn -gridView $byoAppsGridView -header "Exit Codes" -binding "AdditionalExitCodes" -width 100 -headerHorizontalAlignment Left
|
|
Add-SortableColumn -gridView $byoAppsGridView -header "Ignore Exit Codes" -binding "IgnoreExitCodes" -width 120 -headerHorizontalAlignment Left
|
|
Add-SortableColumn -gridView $byoAppsGridView -header "Copy Status" -binding "CopyStatus" -width 150 -headerHorizontalAlignment Left
|
|
|
|
# Keep BYO application columns sized to the current visible content.
|
|
Enable-ListViewColumnAutoResize -ListView $State.Controls.lstApplications -FixedColumnIndexes @(0)
|
|
|
|
# Apps Script Variables ListView setup
|
|
# Bind ItemsSource to the data list
|
|
$State.Controls.lstAppsScriptVariables.ItemsSource = $State.Data.appsScriptVariablesDataList.ToArray()
|
|
|
|
# Set ListViewItem style to stretch content horizontally so cell templates fill the cell
|
|
$itemStyleAppsScriptVars = New-Object System.Windows.Style([System.Windows.Controls.ListViewItem])
|
|
if ($null -ne $listViewItemBaseStyle) { $itemStyleAppsScriptVars.BasedOn = $listViewItemBaseStyle }
|
|
$itemStyleAppsScriptVars.Setters.Add((New-Object System.Windows.Setter([System.Windows.Controls.ListViewItem]::HorizontalContentAlignmentProperty, [System.Windows.HorizontalAlignment]::Stretch)))
|
|
$State.Controls.lstAppsScriptVariables.ItemContainerStyle = $itemStyleAppsScriptVars
|
|
|
|
# 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 -State $State -HeaderCheckBoxKeyName "chkSelectAllAppsScriptVariables" -ColumnWidth 60
|
|
|
|
# Make Key and Value columns sortable
|
|
$appsScriptVarsGridView = $State.Controls.lstAppsScriptVariables.View
|
|
|
|
# Key Column (should be at index 1 after selectable column is inserted at 0)
|
|
if ($appsScriptVarsGridView.Columns.Count -gt 1) {
|
|
$keyColumn = $appsScriptVarsGridView.Columns[1]
|
|
$keyHeader = New-Object System.Windows.Controls.GridViewColumnHeader
|
|
$keyHeader.Content = "Key"
|
|
$keyHeader.Tag = "Key" # Property to sort by
|
|
$keyHeader.HorizontalContentAlignment = [System.Windows.HorizontalAlignment]::Left
|
|
$keyColumn.Header = $keyHeader
|
|
}
|
|
|
|
# Value Column (should be at index 2)
|
|
if ($appsScriptVarsGridView.Columns.Count -gt 2) {
|
|
$valueColumn = $appsScriptVarsGridView.Columns[2]
|
|
$valueHeader = New-Object System.Windows.Controls.GridViewColumnHeader
|
|
$valueHeader.Content = "Value"
|
|
$valueHeader.Tag = "Value" # Property to sort by
|
|
$valueHeader.HorizontalContentAlignment = [System.Windows.HorizontalAlignment]::Left
|
|
$valueColumn.Header = $valueHeader
|
|
}
|
|
|
|
# Add Click event handler for sorting
|
|
$State.Controls.lstAppsScriptVariables.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
|
|
}
|
|
}
|
|
)
|
|
|
|
# Keep apps script variable columns sized to the current visible content.
|
|
Enable-ListViewColumnAutoResize -ListView $State.Controls.lstAppsScriptVariables -FixedColumnIndexes @(0)
|
|
}
|
|
else {
|
|
WriteLog "Warning: lstAppsScriptVariables.View is not a GridView. Selectable column not added, and sorting cannot be enabled."
|
|
}
|
|
|
|
# Build dynamic multi-column checkboxes for optional features
|
|
if ($State.Controls.featuresPanel -and $State.Defaults.windowsSettingsDefaults) {
|
|
BuildFeaturesGrid -parent $State.Controls.featuresPanel -allowedFeatures $State.Defaults.windowsSettingsDefaults.AllowedFeatures -State $State
|
|
}
|
|
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])
|
|
if ($null -ne $listViewItemBaseStyle) { $itemStyleUSBDrives.BasedOn = $listViewItemBaseStyle }
|
|
$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
|
|
}
|
|
|
|
# Unique ID Column (index 1 in XAML, now 2)
|
|
if ($usbDrivesGridView.Columns.Count -gt 2) {
|
|
$uniqueIdColumn = $usbDrivesGridView.Columns[2]
|
|
$uniqueIdHeader = New-Object System.Windows.Controls.GridViewColumnHeader
|
|
$uniqueIdHeader.Content = "Unique ID"
|
|
$uniqueIdHeader.Tag = "UniqueId" # Property to sort by
|
|
$uniqueIdHeader.HorizontalContentAlignment = [System.Windows.HorizontalAlignment]::Left
|
|
$uniqueIdColumn.Header = $uniqueIdHeader
|
|
}
|
|
|
|
# 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
|
|
}
|
|
}
|
|
)
|
|
|
|
# Keep USB drive columns sized to the current visible content.
|
|
Enable-ListViewColumnAutoResize -ListView $State.Controls.lstUSBDrives -FixedColumnIndexes @(0)
|
|
}
|
|
else {
|
|
WriteLog "Warning: lstUSBDrives.View is not a GridView. Selectable column not added, and sorting cannot be enabled."
|
|
}
|
|
|
|
# Additional FFUs ListView setup
|
|
$itemStyleAdditionalFFUs = New-Object System.Windows.Style([System.Windows.Controls.ListViewItem])
|
|
if ($null -ne $listViewItemBaseStyle) { $itemStyleAdditionalFFUs.BasedOn = $listViewItemBaseStyle }
|
|
$itemStyleAdditionalFFUs.Setters.Add((New-Object System.Windows.Setter([System.Windows.Controls.ListViewItem]::HorizontalContentAlignmentProperty, [System.Windows.HorizontalAlignment]::Stretch)))
|
|
$State.Controls.lstAdditionalFFUs.ItemContainerStyle = $itemStyleAdditionalFFUs
|
|
|
|
if ($State.Controls.lstAdditionalFFUs.View -is [System.Windows.Controls.GridView]) {
|
|
Add-SelectableGridViewColumn -ListView $State.Controls.lstAdditionalFFUs -State $State -HeaderCheckBoxKeyName "chkSelectAllAdditionalFFUs" -ColumnWidth 70
|
|
|
|
$additionalFFUsGridView = $State.Controls.lstAdditionalFFUs.View
|
|
|
|
if ($additionalFFUsGridView.Columns.Count -gt 1) {
|
|
$nameColumn = $additionalFFUsGridView.Columns[1]
|
|
$nameHeader = New-Object System.Windows.Controls.GridViewColumnHeader
|
|
$nameHeader.Content = "FFU Name"
|
|
$nameHeader.Tag = "Name"
|
|
$nameHeader.HorizontalContentAlignment = [System.Windows.HorizontalAlignment]::Left
|
|
$nameColumn.Header = $nameHeader
|
|
}
|
|
if ($additionalFFUsGridView.Columns.Count -gt 2) {
|
|
$lastModColumn = $additionalFFUsGridView.Columns[2]
|
|
$lastModHeader = New-Object System.Windows.Controls.GridViewColumnHeader
|
|
$lastModHeader.Content = "Last Modified"
|
|
$lastModHeader.Tag = "LastModified"
|
|
$lastModHeader.HorizontalContentAlignment = [System.Windows.HorizontalAlignment]::Left
|
|
$lastModColumn.Header = $lastModHeader
|
|
}
|
|
|
|
$State.Controls.lstAdditionalFFUs.AddHandler(
|
|
[System.Windows.Controls.GridViewColumnHeader]::ClickEvent,
|
|
[System.Windows.RoutedEventHandler] {
|
|
param($eventSource, $e)
|
|
$header = $e.OriginalSource
|
|
if ($header -is [System.Windows.Controls.GridViewColumnHeader] -and $header.Tag) {
|
|
$listViewControl = $eventSource
|
|
$window = [System.Windows.Window]::GetWindow($listViewControl)
|
|
$uiStateFromWindowTag = $window.Tag
|
|
Invoke-ListViewSort -listView $eventSource -property $header.Tag -State $uiStateFromWindowTag
|
|
}
|
|
}
|
|
)
|
|
|
|
# Keep additional FFU columns sized to the current visible content.
|
|
Enable-ListViewColumnAutoResize -ListView $State.Controls.lstAdditionalFFUs -FixedColumnIndexes @(0)
|
|
}
|
|
else {
|
|
WriteLog "Warning: lstAdditionalFFUs.View is not a GridView. Selectable column not added, and sorting cannot be enabled."
|
|
}
|
|
}
|
|
|
|
|
|
Export-ModuleMember -Function *
|