{"record":{"id":"783cca6f87ea1471","repo":"dotnet/wpf","slug":"sr-routedeventcannotchangewhilerouting","errorCode":null,"errorMessage":"SR.RoutedEventCannotChangeWhileRouting","messagePattern":"SR\\.RoutedEventCannotChangeWhileRouting","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/RoutedEventArgs.cs","lineNumber":90,"sourceCode":"\n        #endregion Construction\n\n        #region External API\n        /// <summary>\n        ///     Returns the <see cref=\"RoutedEvent\"/> associated\n        ///     with this <see cref=\"RoutedEventArgs\"/>\n        /// </summary>\n        /// <remarks>\n        ///     The <see cref=\"RoutedEvent\"/> cannot be null\n        ///     at any time\n        /// </remarks>\n        public RoutedEvent RoutedEvent\n        {\n            get {return _routedEvent;}\n            set\n            {\n                if (UserInitiated && InvokingHandler)\n                    throw new InvalidOperationException(SR.RoutedEventCannotChangeWhileRouting);\n\n                _routedEvent = value;\n            }\n        }\n\n        /// <summary>\n        ///     Changes the RoutedEvent assocatied with these RoutedEventArgs\n        /// </summary>\n        /// <remarks>\n        ///     Only used internally.  Added to support cracking generic MouseButtonDown/Up events\n        ///     into MouseLeft/RightButtonDown/Up events.\n        /// </remarks>\n        /// <param name=\"newRoutedEvent\">\n        ///     The new RoutedEvent to associate with these RoutedEventArgs\n        /// </param>\n        internal void OverrideRoutedEvent( RoutedEvent newRoutedEvent )\n        {\n            _routedEvent = newRoutedEvent;","sourceCodeStart":72,"sourceCodeEnd":108,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/RoutedEventArgs.cs#L72-L108","documentation":"RoutedEventArgs.RoutedEvent cannot be changed while the event is actively being routed through a handler that was user-initiated. The setter throws InvalidOperationException if UserInitiated && InvokingHandler, because changing the routed event mid-route would corrupt the event pipeline.","triggerScenarios":"Inside a routed-event handler (or class handler) invoked for a user-initiated event, assigning e.RoutedEvent = someOtherRoutedEvent to try to re-target or re-type the event during routing.","commonSituations":"Handlers attempting to 'convert' an event (e.g. re-raise PreviewMouseDown as MouseDown) by mutating the args; framework code reusing RoutedEventArgs instances across events; command/bubble interception logic.","solutions":["Do not change RoutedEvent inside a handler; instead call RaiseEvent with a new RoutedEventArgs configured with the desired RoutedEvent.","Clone/reconstruct the args: new MouseEventArgs(...) with the target RoutedEvent and raise it explicitly.","Mark the original args handled (e.Handled = true) and raise the substitute event separately.","If mutation is needed for internal reuse, do it outside handler invocation (before RaiseEvent)."],"exampleFix":"// before\nprotected override void OnPreviewMouseDown(MouseButtonEventArgs e)\n{\n    e.RoutedEvent = Mouse.MouseDownEvent; // throws during routing\n    base.OnMouseDown(e);\n}\n\n// after\nprotected override void OnPreviewMouseDown(MouseButtonEventArgs e)\n{\n    var args = new MouseButtonEventArgs(e.MouseDevice, e.Timestamp, e.ChangedButton)\n    { RoutedEvent = Mouse.MouseDownEvent };\n    RaiseEvent(args);\n}","handlingStrategy":"try-catch","validationCode":"if (args.UserInitiated && args.RoutedEvent != desiredEvent)\n{\n    // raise a new event instead of mutating\n}","typeGuard":null,"tryCatchPattern":"try { args.RoutedEvent = otherEvent; }\ncatch (InvalidOperationException)\n{\n    // fall back: raise a fresh RoutedEventArgs with the desired RoutedEvent\n}","preventionTips":["Treat RoutedEventArgs.RoutedEvent as immutable during handler execution.","Raise new, properly configured args instead of re-targeting existing ones.","Mark original events handled and raise substitute events separately.","Avoid reusing RoutedEventArgs instances across multiple RaiseEvent calls."],"tags":["wpf","routed-events","invalid-state"],"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"}