{"record":{"id":"d1c86e4206d16ca3","repo":"dotnet/wpf","slug":"sr-format-sr-texteditorcannotregistercommandhandler-type","errorCode":null,"errorMessage":"SR.Format(SR.TextEditorCanNotRegisterCommandHandler, ((Type)_registeredEditingTypes[i]).Name, controlType.Name)","messagePattern":"SR\\.Format\\(SR\\.TextEditorCanNotRegisterCommandHandler, \\(\\(Type\\)_registeredEditingTypes\\[i\\]\\)\\.Name, controlType\\.Name\\)","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Documents/TextEditor.cs","lineNumber":325,"sourceCode":"        {\n            // Check if we already registered handlers for this type\n            Invariant.Assert(_registeredEditingTypes != null);\n            lock (_registeredEditingTypes)\n            {\n                for (int i = 0; i < _registeredEditingTypes.Count; i++)\n                {\n                    // If controlType is or derives from some already registered class - we are done\n                    if (((Type)_registeredEditingTypes[i]).IsAssignableFrom(controlType))\n                    {\n                        return;\n                    }\n\n                    // Check if controlType is not a superclass of some registered class.\n                    // This is erroneus condition, which must be avoided.\n                    // Otherwise the same handlers will be attached to some class twice.\n                    if (controlType.IsAssignableFrom((Type)_registeredEditingTypes[i]))\n                    {\n                        throw new InvalidOperationException(\n                            SR.Format(SR.TextEditorCanNotRegisterCommandHandler, ((Type)_registeredEditingTypes[i]).Name, controlType.Name));\n                    }\n                }\n\n                // The class was not yet registered. Add it to the list before starting registering handlers.\n                _registeredEditingTypes.Add(controlType);\n            }\n\n            // Mouse\n            TextEditorMouse._RegisterClassHandlers(controlType, registerEventListeners);\n            if (!readOnly)\n            {\n                // Typing\n                TextEditorTyping._RegisterClassHandlers(controlType, registerEventListeners);\n            }\n            // Drag-and-drop\n            TextEditorDragDrop._RegisterClassHandlers(controlType, readOnly, registerEventListeners);\n            // Cut-Copy-Paste","sourceCodeStart":307,"sourceCodeEnd":343,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Documents/TextEditor.cs#L307-L343","documentation":"TextEditor.RegisterCommandHandlers maintains a static list of control types that already registered editing command handlers. If a new controlType is a superclass of an already-registered type, the same handlers would be attached twice, so the registration throws InvalidOperationException naming both types. It is a guard against duplicate/base-class handler registration.","triggerScenarios":"A custom control deriving from (or being a base class of) a control type that already called RegisterCommandHandlers calls TextEditor.RegisterCommandHandlers for the same TextEditor instance.","commonSituations":"Registering editing handlers in a control hierarchy where both a base and derived control attempt registration; registering the same control type twice during app initialization or XAML loading.","solutions":["Register only the most-derived control type once; remove the redundant registration.","Check TextEditor's registered types (or guard with a static bool) before calling RegisterCommandHandlers.","Move registration to a single point (e.g. static constructor of the leaf type)."],"exampleFix":"// before\nTextEditor.RegisterCommandHandlers(controlType, ...); // called in both BaseControl and DerivedControl\n// after\nprotected static bool _handlersRegistered;\nif (!_handlersRegistered)\n{\n    TextEditor.RegisterCommandHandlers(controlType, ...);\n    _handlersRegistered = true;\n}","handlingStrategy":"validation","validationCode":"if (TextEditorHelpers.IsRegistered(controlType)) return; // guard before calling RegisterCommandHandlers","typeGuard":null,"tryCatchPattern":"try { TextEditor.RegisterCommandHandlers(controlType, ...); }\ncatch (InvalidOperationException) { /* already registered via a derived type; skip */ }","preventionTips":["Register command handlers from exactly one type in a hierarchy","Use a static registration flag","Prefer registering leaf-most control types only"],"tags":["wpf","command-handling","registration"],"backgroundTag":"invalid-state-transition","analyzedSha":"81131a70a4c573cd62748a5c36908fc4d662daa9","analyzedAt":"2026-09-14T10:12:48.479Z","contentChangedAt":"2026-09-14T10:12:48.479Z","schemaVersion":2},"datasetVersion":"2026-09-21T21:30:21.729Z"}