Hardware Pickers

Hardware picker controls for selecting connected serial ports, USB devices, USB cameras and audio endpoints with live device-state detection (connect, disconnect, in-use).

Table of Contents

Overview

Atc.Wpf.Hardware provides twelve picker controls, each with a labeled variant:

  • SerialPortPicker / LabelSerialPortPicker — select a serial / COM port
  • UsbPortPicker / LabelUsbPortPicker — select a connected USB device
  • UsbCameraPicker / LabelUsbCameraPicker — select a video-capture device
  • AudioInputPicker / LabelAudioInputPicker — select a microphone / capture endpoint
  • AudioOutputPicker / LabelAudioOutputPicker — select speakers / a render endpoint
  • BluetoothDevicePicker / LabelBluetoothDevicePicker — select a paired Bluetooth device
  • DrivePicker / LabelDrivePicker — select a logical drive (fixed / removable / network / CD)
  • ProcessPicker / LabelProcessPicker — inspection picker for running OS processes
  • WindowPicker / LabelWindowPicker — inspection picker for top-level OS windows
  • NetworkAdapterPicker / LabelNetworkAdapterPicker — select a NIC / Wi-Fi / VPN / loopback adapter
  • PrinterPicker / LabelPrinterPicker — select an installed printer / print queue
  • DisplayPicker / LabelDisplayPicker — select a connected display / monitor

The system-locale TimeZonePicker / LabelTimeZonePicker lives in Atc.Wpf.Forms — it has no hardware involvement.

The six WinRT-backed pickers share infrastructure (DeviceWatcherHost) using Windows.Devices.Enumeration.DeviceWatcher. DrivePicker, ProcessPicker, WindowPicker, NetworkAdapterPicker, PrinterPicker, and DisplayPicker share a polling host (PollingServiceHost): a thread-pool timer (default 2 s, configurable) runs the enumeration off the UI thread and applies the result on the UI dispatcher (DrivePicker also reads volume details on the UI thread). The consuming app reads the same DeviceState shape regardless of source — hot-plug, disconnect and in-use changes update the picker live so the user never has to click Refresh and never picks a device that's silently unusable.

Quick Reference

Control Selected Value Type Source API
SerialPortPicker SerialPortInfo? Windows.Devices.SerialCommunication.SerialDevice
UsbPortPicker UsbDeviceInfo? DeviceInformation filtered by USB device interface class (or UsbDeviceClassFilter flags → AQS)
UsbCameraPicker UsbCameraInfo? DeviceInformation.FindAllAsync(DeviceClass.VideoCapture)
AudioInputPicker AudioDeviceInfo? DeviceInformation.FindAllAsync(DeviceClass.AudioCapture)
AudioOutputPicker AudioDeviceInfo? DeviceInformation.FindAllAsync(DeviceClass.AudioRender)
BluetoothDevicePicker BluetoothDeviceInfo? BluetoothDevice.GetDeviceSelectorFromPairingState(true) (paired classic)
DrivePicker DiskDriveInfo? System.IO.DriveInfo.GetDrives() + 2 s polling
ProcessPicker RunningProcessInfo? Process.GetProcesses() + 2 s polling
WindowPicker TopLevelWindowInfo? EnumWindows P/Invoke + 2 s polling
NetworkAdapterPicker NetworkAdapterInfo? NetworkInterface.GetAllNetworkInterfaces() + 2 s polling
PrinterPicker PrinterInfo? LocalPrintServer.GetPrintQueues() + 2 s polling
DisplayPicker DisplayInfo? EnumDisplayMonitors + GetMonitorInfo P/Invoke + 2 s polling

Device-State UX

Each item in a picker dropdown has a coloured status dot:

State Dot Trigger
Available 🟢 green enumerated, free to use
JustConnected 🟢 green hot-plugged within last 3 s, briefly highlighted
InUse 🟠 amber held by another process / interface disabled
Disconnected 🔴 red was selected, now physically gone

When a bound Value device disconnects:

  • An inline warning appears under the dropdown ("Device disconnected").
  • The picker raises DeviceLost.
  • The Value is kept by default (preserves user intent through USB jiggle); set ClearValueOnDisconnect="True" to opt out.
  • When the same device reappears, the picker auto-rebinds and raises DeviceReconnected (turn off via AutoRebindOnReconnect="False").

Common Properties

These properties exist on every hardware picker (and their Label* wrappers):

Property Type Default Notes
Value T? null The selected device (TwoWay)
WatermarkText string "" Empty-state placeholder
ShowRefreshButton bool true Always-visible 🔄 button
AutoRefreshOnDeviceChange bool true Watch for device changes (DeviceWatcher or polling); can be toggled at runtime
DetectInUseState bool false Opt-in active probe (Serial / USB only)
ClearValueOnDisconnect bool false Preserve user intent by default
AutoRebindOnReconnect bool true Match by DeviceId
AutoSelectFirstAvailable bool false Avoid surprise rebinding
ItemTemplate DataTemplate? default Override status dot + name layout (picker only, not on the Label* wrappers)

The polling pickers (ProcessPicker, WindowPicker, DrivePicker, PrinterPicker, DisplayPicker, NetworkAdapterPicker) also expose their service tuning — PollingInterval, and OnlyWithMainWindow, OnlyVisibleWithTitle or IncludeLoopback where relevant. These are nullable: null (default) keeps the service's own setting, a value is pushed to the service immediately. The Label* wrappers do not forward these tuning properties yet.

Sharing or injecting a service

Every picker has a public constructor that takes its service interface (for example new ProcessPicker(IProcessService service)). Use it to share one watcher between several pickers or to supply a test double. The picker does not dispose a service passed in this way.

Localization

User-visible strings ("Refresh", "Available", "In use", "Disconnected", validation messages) ship as .resx triplets:

  • en-US (invariant)
  • da-DK
  • de-DE

Set Thread.CurrentThread.CurrentUICulture before showing the picker to switch language.

Target Framework

Atc.Wpf.Hardware targets net10.0-windows10.0.19041.0 (Windows 10 May 2020 / 2004 and later, all Windows 11). This is required for Windows.Devices.Enumeration.DeviceWatcher and the WinRT projection. Consumers need the same TFM or higher.