Public/Show-RpItemPicker.ps1
function Show-RpItemPicker { <# .SYNOPSIS Displays an item picker dialog and allows selection of items based on specified types such as Camera, Hardware, or Server. .DESCRIPTION The Show-RpItemPicker function opens a window with a customizable item picker control. Users can select items categorized as Camera, Hardware, or Server. The function supports configuration for displaying only camera items and checks the connection to the VMS system before proceeding. .PARAMETERS -Title Specifies the title of the item picker window. Default is "Select Item(s)". -Kind Defines the types of items to be displayed in the picker. Accepts multiple values from 'Camera', 'Hardware', 'Server'. -ConfigItemsCamsOnly When specified, filters the results to return only camera items. -CheckConnection Checks the VMS connection before showing the item picker. If the connection fails, the function will not proceed. .COMPONENT CustomVMSCmdlets .EXAMPLE Show-RpItemPicker -Title "Select Cameras" -Kind 'Camera' Opens the item picker with the title "Select Cameras" displaying only camera items. .EXAMPLE Show-RpItemPicker -Title "Hardware Selection" -Kind 'Hardware' -CheckConnection Checks the connection first, then shows a picker for selecting hardware items. .NOTES This function relies on the VideoOS.Platform.UI module for UI elements and VideoOS.Platform.SDK to interact with the VMS system. Proper error handling is implemented to manage any exceptions during the operation, ensuring the application remains stable even if an error occurs. .LINK Further documentation on ItemPickerWpfUserControl item management can be found at the official documentation portal. https://doc.developer.milestonesys.com/html/index.html .LINK https://www.remotepro.dev/en-US/Show-RpItemPicker #> [CmdletBinding(DefaultParameterSetName='VideoOS.Platform.SDK.Platform')] param ( [Parameter(Mandatory=$true)] [string]$Title = "Select Item(s)", [Parameter(Mandatory=$true)] [ValidateSet("Camera", "Hardware", "Server")] [string[]]$Kind, [Parameter(Mandatory=$false)] [switch]$ConfigItemsCamsOnly, [Parameter(Mandatory=$false)] [switch]$CheckConnection ) begin { # ToDo: Remove this line when the module is imported in the script # replace with correct reference to the module Import-Module -Name RemotePro Add-Type -AssemblyName PresentationFramework $connectionValid = $true if ($CheckConnection) { if (-not (Test-RpVmsConnection -ShowErrorDialog $true)) { $connectionValid = $false } } } process { if (-not $connectionValid) { Write-Host "Connection validation failed. No VMS connection available." return } # Define the XAML with the button included $xaml = @" <Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" xmlns:mdControls="clr-namespace:MaterialDesignThemes.Wpf;assembly=MaterialDesignThemes.Wpf" Title="Milestone Item Picker" Height="600" Width="800" Background="{DynamicResource MaterialDesignPaper}"> <Window.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesign2.Defaults.xaml" /> <materialDesign:BundledTheme BaseTheme="Light" PrimaryColor="Grey" SecondaryColor="Lime" /> </ResourceDictionary.MergedDictionaries> </ResourceDictionary> </Window.Resources> <Grid x:Name="mainGrid" Margin="10"> <Grid.RowDefinitions> <RowDefinition Height="*" /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> <!-- Content Control for item picker --> <ContentControl x:Name="itemPickerHost" Grid.Row="0" Margin="5" /> <!-- Material Design styled button matching previous color scheme --> <Button Content="Get Selected Items" Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="10" Padding="10,5" Style="{StaticResource MaterialDesignRaisedButton}" Background="{DynamicResource PrimaryHueMidBrush}" Foreground="{DynamicResource PrimaryHueLightForegroundBrush}" BorderBrush="{DynamicResource PrimaryHueDarkBrush}" /> </Grid> </Window> "@ # Convert the XAML string to XML $reader = [System.Xml.XmlNodeReader]::new([xml]$xaml) # Load the XAML $window = [System.Windows.Markup.XamlReader]::Load($reader) # Set the window icon if ($null -ne $window) { Set-RpWindowIcon -window $window } else { Write-Warning "WPF window failed to load. Cannot set icon." } # Create an instance of the ItemPickerWpfUserControl $itemPickerControl = New-Object VideoOS.Platform.UI.ItemPickerWpfUserControl # Set properties to customize the behavior of the control $itemPickerControl.AllowGroupSelection = $true $itemPickerControl.AutoExpand = $true $itemPickerControl.EmptyListOverlayText = "No items selected" $itemPickerControl.IsMultiSelection = $true $itemPickerControl.SearchEnabled = $true $itemPickerControl.SearchPlaceholderText = "Search for items..." $itemPickerControl.TableHeader = "Selected Items" # Initialize the items list $itemsList = New-Object 'System.Collections.Generic.List[VideoOS.Platform.Item]' function Get-KindGuid { param ($kindName) switch ($kindName) { "Camera" { return [VideoOS.Platform.Kind]::Camera } "Hardware" { return [VideoOS.Platform.Kind]::Hardware } "Server" { return [VideoOS.Platform.Kind]::Server } default { throw "Unknown kind: $kindName" } } } # Retrieve items from the server based on Kind if ($Kind -and $Kind.Count -gt 0) { foreach ($kindName in $Kind) { $kindGuid = Get-KindGuid -kindName $kindName $items = Get-VmsVideoOSItem -Kind $kindGuid -ItemHierarchy 'SystemDefined' -FolderType 'SystemDefined' if ($items) { foreach ($item in $items) { if ($item -is [VideoOS.Platform.Item]) { $itemsList.Add($item) } } } } } else { $items = Get-VmsVideoOSItem -ItemHierarchy 'SystemDefined' -FolderType 'SystemDefined' -Verbose foreach ($item in $items) { if ($item -is [VideoOS.Platform.Item]) { $itemsList.Add($item) } } } if ($itemsList.Count -gt 0) { # Set the Items property directly $itemPickerControl.Items = $itemsList } else { Write-Verbose "No items retrieved from the server" } $script:selectedItemDetails = @() try { # Event handler for the button click $button = $window.FindName("mainGrid").Children | Where-Object { $_ -is [System.Windows.Controls.Button] } $button.Add_Click({ $script:selectedItemDetails = $itemPickerControl.SelectedItems | ForEach-Object { @{ Name = $_.Name Id = $_.FQID.ObjectId FQID = $_.FQID } } Write-Verbose "Number of selected items: $($script:selectedItemDetails.Count)" foreach ($item in $script:selectedItemDetails) { Write-Verbose "Selected item: Name=$($item.Name), Id=$($item.Id), FQID=$($item.FQID)" } $null = $window.DialogResult = $true $window.Close() }) # Add the ItemPickerWpfUserControl to the ContentControl $itemPickerHost = $window.FindName("itemPickerHost") $itemPickerHost.Content = $itemPickerControl # Show the WPF window $null = $window.ShowDialog() # Filter the original items based on the selected item IDs $script:selectedItems = $itemPickerControl.SelectedItems | Where-Object { $script:selectedItemDetails.Id -contains $_.FQID.ObjectId } # Debug output to check what is being returned Write-Verbose "`nReturning $($script:selectedItems.Count)items:" foreach ($item in $script:selectedItems) { Write-Verbose "Returning item: Name=$($item.Name), Id=$($item.FQID.ObjectId), FQID=$($item.FQID)" } # Switch and logic for return items of type VideoOS.Platform.ConfigurationItems.Camera if ($ConfigItemsCamsOnly){ # Final type = VideoOS.Platform.ConfigurationItems.Camera $cameras = [System.Collections.Generic.List[VideoOS.Platform.ConfigurationItems.Camera]]::new() foreach ($item in $script:selectedItems){ switch ($item.GetType().FullName) { #Switches ensures selected object types get handled correctly. #region Camera Items "VideoOS.Platform.SDK.Platform.CameraItem" { # Convert Camera objects from type Platform.SDK to Configuration $camera = Get-VmsCamera -Id $item.FQID.ObjectId $cameras.Add($camera) } #endregion #region Hardware Items "VideoOS.Platform.SDK.Platform.HardwareItem" { # Convert Hardware objects from type Platform to Configruation $configItemCam = Get-VmsHardware -id $item.FQID.ObjectId.ToString() | Get-VmsCamera $cameras.Add($configItemCam) } #endregion #region All Hardware folders "VideoOS.Platform.SDK.Platform.HardwareFolderItem" { # VideoOS.Platform.SDK.Platform.HardwareFolderItem $hwFolder = $item.GetChildren() # VideoOS.Platform.ConfigurationItems.Hardware $hwItems = $hwFolder.Values | Get-VmsHardware # Final Conversion: Completed type to VideoOS.Platform.SDK.Platform.CameraItem foreach ($hw in $hwItems) { $configItemCam = $hw | Get-VmsCamera $cameras.Add($configItemCam) } } #endregion #region All Camera folders "VideoOS.Platform.SDK.Platform.AllRSFolderItem" { # VideoOS.Platform.SDK.Platform.AllRSFolderItem $camFolder = $item.GetChildren() # Final Conversion: Completed type to VideoOS.Platform.SDK.Platform.CameraItem foreach ($cam in $camFolder) { $camera = Get-VmsCamera -Id $cam.FQID.ObjectId $cameras.Add($camera) } } #endregion #region Recording Server Folders "VideoOS.Platform.SDK.Platform.ServerFolderByTypeItem" { # Unnroll recording servers $srvFolderChildren = $item.GetChildren() # (plural) VideoOS.Platform.SDK.Platform.RecorderFolderByTypeItem to VideoOS.Platform.ConfigurationItems.RecordingServer $recServers = $srvFolderChildren | Get-RecordingServer # Final Conversion: Completed type to VideoOS.Platform.SDK.Platform.CameraItem foreach ($server in $recServers) { $server | Get-VmsHardware | Get-VmsCamera | ForEach-Object { $cameras.Add($_) } } } #endregion #region Recording Servers "VideoOS.Platform.SDK.Platform.ServerFolderByTypeItem" { # (single) VideoOS.Platform.SDK.Platform.RecorderFolderByTypeItem to VideoOS.Platform.ConfigurationItems.RecordingServer $recServer = $item | Get-RecordingServer # Final Conversion: Completed type to VideoOS.Platform.SDK.Platform.CameraItem $recServer | Get-VmsHardware | Get-VmsCamera | ForEach-Object { $cameras.Add($_) } } #endregion } } return $cameras # VideoOS.Platform.ConfigurationItems.Camera } else { return $script:selectedItems # VideoOS.Platform.SDK.Platform } } catch { Write-Error "An error occurred: $_" } finally { # Properly dispose of the window and control if ($null -ne $itemPickerControl) { $itemPickerControl.Dispose() } if ($null -ne $window) { $window.Close() } } } } |