dotnet/wpf · error · ArgumentException
SR.ClassTypeIllegal
Error message
SR.ClassTypeIllegal
What it means
EventManager.RegisterClassHandler only accepts class types deriving from UIElement, ContentElement, or UIElement3D, since class handling is implemented on those element cores. A classType outside that hierarchy throws ArgumentException with SR.ClassTypeIllegal. This is validated before the handler-legality check.
Solutions
- Pass a class type deriving from UIElement, UIElement3D, or ContentElement
- Register handlers on the nearest element base class that is in the allowed hierarchy
- Move the handler registration to the element class itself instead of an unrelated class
Example fix
// before EventManager.RegisterClassHandler(typeof(MyService), Mouse.MouseDownEvent, handler, false); // after EventManager.RegisterClassHandler(typeof(MyElement), Mouse.MouseDownEvent, new MouseButtonEventHandler(handler), false);
Defensive patterns
Strategy: validation
Validate before calling
bool ok = typeof(UIElement).IsAssignableFrom(classType) || typeof(ContentElement).IsAssignableFrom(classType) || typeof(UIElement3D).IsAssignableFrom(classType);
Type guard
bool IsClassHandlerTarget(Type t) => typeof(UIElement).IsAssignableFrom(t) || typeof(ContentElement).IsAssignableFrom(t) || typeof(UIElement3D).IsAssignableFrom(t);
Try / catch
try { EventManager.RegisterClassHandler(classType, evt, handler, false); } catch (ArgumentException) { /* classType not an element type */ } Prevention
- Only register class handlers on UIElement/UIElement3D/ContentElement-derived types
- Constrain generic helpers with `where T : UIElement`
- Double-check typeof() arguments for typos
When it happens
Trigger: Calling RegisterClassHandler with a type that does not derive from UIElement/ContentElement/UIElement3D — e.g. a plain Control-derived non-visual class, a service class, or a DependencyObject that is not an element.
Common situations: Attempting class handling on DispatcherObject/DependencyObject subclasses; wiring handlers for custom non-element classes; typo passing typeof(HandlerClass) instead of typeof(ElementClass).
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- InvalidEnumArgumentException: routingStrategy
- SR.HandlerTypeIllegal
- SR.HandlerTypeIllegal
- SR.Mismatched_RoutedEvent
- SR.SourceNotSet
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/bf7664c81fb11f7d.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/EventManager.cs:159
/// </param>
/// <ExternalAPI/>
public static void RegisterClassHandler(
Type classType,
RoutedEvent routedEvent,
Delegate handler,
bool handledEventsToo)
{
ArgumentNullException.ThrowIfNull(classType);
ArgumentNullException.ThrowIfNull(routedEvent);
ArgumentNullException.ThrowIfNull(handler);
if (!typeof(UIElement).IsAssignableFrom(classType) &&
!typeof(ContentElement).IsAssignableFrom(classType) &&
!typeof(UIElement3D).IsAssignableFrom(classType))
{
throw new ArgumentException(SR.ClassTypeIllegal);
}
if (!routedEvent.IsLegalHandler(handler))
{
throw new ArgumentException(SR.HandlerTypeIllegal);
}
GlobalEventManager.RegisterClassHandler(classType, routedEvent, handler, handledEventsToo);
}
/// <summary>
/// Returns <see cref="RoutedEvent"/>s
/// that have been registered so far
/// </summary>
/// <remarks>
/// Also see
/// <see cref="EventManager.RegisterRoutedEvent"/>
/// <para/>View on GitHub (pinned to 81131a70a4)