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 portUsbPortPicker/LabelUsbPortPicker— select a connected USB deviceUsbCameraPicker/LabelUsbCameraPicker— select a video-capture deviceAudioInputPicker/LabelAudioInputPicker— select a microphone / capture endpointAudioOutputPicker/LabelAudioOutputPicker— select speakers / a render endpointBluetoothDevicePicker/LabelBluetoothDevicePicker— select a paired Bluetooth deviceDrivePicker/LabelDrivePicker— select a logical drive (fixed / removable / network / CD)ProcessPicker/LabelProcessPicker— inspection picker for running OS processesWindowPicker/LabelWindowPicker— inspection picker for top-level OS windowsNetworkAdapterPicker/LabelNetworkAdapterPicker— select a NIC / Wi-Fi / VPN / loopback adapterPrinterPicker/LabelPrinterPicker— select an installed printer / print queueDisplayPicker/LabelDisplayPicker— select a connected display / monitor
The system-locale
TimeZonePicker/LabelTimeZonePickerlives inAtc.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
Valueis kept by default (preserves user intent through USB jiggle); setClearValueOnDisconnect="True"to opt out. - When the same device reappears, the picker auto-rebinds and raises
DeviceReconnected(turn off viaAutoRebindOnReconnect="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-DKde-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.