dotnet/wpf · error · InvalidOperationException
SR.HwndHostDoesNotSupportChildKeyboardSinks
Error message
SR.HwndHostDoesNotSupportChildKeyboardSinks
What it means
HwndHost does not support child keyboard input sinks: its virtual RegisterKeyboardInputSinkCore deliberately throws InvalidOperationException with SR.HwndHostDoesNotSupportChildKeyboardSinks. Unlike HwndSource, an HwndHost cannot register nested IKeyboardInputSink components for Tab/keyboard routing.
Solutions
- Do not register child keyboard sinks with HwndHost; remove the RegisterKeyboardInputSink call.
- Restructure so the child is hosted in an HwndSource if sink registration is required.
- Override RegisterKeyboardInputSinkCore in a derived HwndHost class to implement sink support yourself.
- Handle keyboard interop via standard focus/Tab routing (e.g. IKeyboardInputSink on the top-level HwndSource) instead.
Example fix
// before var site = ((IKeyboardInputSink)hwndHost).RegisterKeyboardInputSink(childSink); // after // HwndHost does not support child sinks; rely on the owning HwndSource var site = ((IKeyboardInputSink)hwndSource).RegisterKeyboardInputSink(childSink);
Defensive patterns
Strategy: type-guard
Validate before calling
if (host is HwndHost)
throw new NotSupportedException("HwndHost does not support child keyboard sinks"); Type guard
bool SupportsChildSinks(IKeyboardInputSink sink) => sink is HwndSource;
Try / catch
try
{
site = ((IKeyboardInputSink)sinkContainer).RegisterKeyboardInputSink(childSink);
}
catch (InvalidOperationException)
{
// fall back to top-level HwndSource sink registration
} Prevention
- Only register child keyboard sinks with HwndSource, never HwndHost.
- Review third-party components that self-register as sinks when embedded.
- Handle keyboard interop through focus and Tab routing instead of sink registration.
When it happens
Trigger: Calling IKeyboardInputSink.RegisterKeyboardInputSink (or the protected RegisterKeyboardInputSinkCore) with a child sink on an HwndHost instance, e.g. hosting a component that tries to register itself as a keyboard sink with an HwndHost-based control.
Common situations: Embedding WindowsFormsHost or other sink-registering children inside an HwndHost-derived control and relying on cross-boundary keyboard sink registration; migrating code from HwndSource to HwndHost.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- SR.ChildWindowMustHaveCorrectParent
- SR.ChildWindowNotCreated
- SR.HostedWindowMustBeAChildWindow
- SR.KeyboardSinkMustBeAnElement
- " }} " element found. Expected fixed page element ( }} ).
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/c901644c24227ea5.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Interop/HwndHost.cs:209
// explicit interface implementations (that do have the property of being hidden from the public
// contract, which limits IntelliSense on derived types like WebBrowser) while sticking protected
// virtuals next to them. Those virtuals contain our base implementation, while the explicit
// interface implementation methods do call trivially into the virtuals.
//
// This comment outlines the security rationale applied to those methods.
//
// <SecurityNote Name="IKeyboardInputSink_Implementation">
// The security attributes on the virtual methods within this region mirror the corresponding
// IKeyboardInputSink methods; customers can override those methods, so we insert a LinkDemand
// to encourage them to have a LinkDemand too (via FxCop).
/// <summary>
/// Registers a IKeyboardInputSink with the HwndSource in order
/// to retreive a unique IKeyboardInputSite for it.
/// </summary>
protected virtual IKeyboardInputSite RegisterKeyboardInputSinkCore(IKeyboardInputSink sink)
{
throw new InvalidOperationException(SR.HwndHostDoesNotSupportChildKeyboardSinks);
}
IKeyboardInputSite IKeyboardInputSink.RegisterKeyboardInputSink(IKeyboardInputSink sink)
{
return RegisterKeyboardInputSinkCore(sink);
}
/// <summary>
/// Gives the component a chance to process keyboard input.
/// Return value is true if handled, false if not. Components
/// will generally call a child component's TranslateAccelerator
/// if they can't handle the input themselves. The message must
/// either be WM_KEYDOWN or WM_SYSKEYDOWN. It is illegal to
/// modify the MSG structure, it's passed by reference only as
/// a performance optimization.
/// </summary>
protected virtual bool TranslateAcceleratorCore(ref MSG msg, ModifierKeys modifiers)
{View on GitHub (pinned to 81131a70a4)