{"record":{"id":"d0ab700576bf78e3","repo":"dotnet/wpf","slug":"sr-cannotbothbenull-formatted-with-newvalue-previousvalue","errorCode":null,"errorMessage":"SR.CannotBothBeNull (formatted with 'newValue', 'previousValue')","messagePattern":"SR\\.CannotBothBeNull \\(formatted with 'newValue', 'previousValue'\\)","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Ink/Events.cs","lineNumber":103,"sourceCode":"    public delegate void PropertyDataChangedEventHandler(object sender, PropertyDataChangedEventArgs e);\n\n    /// <summary>\n    /// Event arg used a change to the drawing attributes associated with one or more strokes has occurred.\n    /// </summary>\n    public class PropertyDataChangedEventArgs : EventArgs\n    {\n        private Guid _propertyGuid;\n        private object _newValue;\n        private object _previousValue;\n\n        /// <summary>Constructor</summary>\n        public PropertyDataChangedEventArgs(Guid propertyGuid,\n                                            object newValue,\n                                            object previousValue)\n        {\n            if ( newValue == null && previousValue == null )\n            {\n                throw new ArgumentException(SR.Format(SR.CannotBothBeNull, \"newValue\", \"previousValue\"));\n            }\n\n            _propertyGuid = propertyGuid;\n            _newValue = newValue;\n            _previousValue = previousValue;\n        }\n\n        /// <summary>\n        /// Gets the property guid that represents the DrawingAttribute that changed\n        /// </summary>\n        public Guid PropertyGuid\n        {\n            get { return _propertyGuid; }\n        }\n\n        /// <summary>\n        /// Gets the new value of the DrawingAttribute\n        /// </summary>","sourceCodeStart":85,"sourceCodeEnd":121,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Ink/Events.cs#L85-L121","documentation":"PropertyDataChangedEventArgs represents a change of a property value, so at least one of newValue/previousValue must be non-null. The constructor throws ArgumentException when both are null because such an event conveys no change.","triggerScenarios":"Raising a PropertyDataChanged event manually with new PropertyDataChangedEventArgs(guid, null, null).","commonSituations":"Custom ExtendedProperties implementations forwarding change notifications with unset values; refactoring code that lost track of old/new values.","solutions":["Supply at least one of newValue/previousValue","Skip raising the event when both values are missing"],"exampleFix":"// before\nnew PropertyDataChangedEventArgs(guid, null, null);\n// after\nif (newValue != null || previousValue != null) raise(new PropertyDataChangedEventArgs(guid, newValue, previousValue));","handlingStrategy":"validation","validationCode":"if (newValue == null && previousValue == null) return; // skip raising event","typeGuard":"static bool IsValidPropertyDataChange(object n, object p) => n != null || p != null;","tryCatchPattern":"try { var e = new PropertyDataChangedEventArgs(guid, newValue, previousValue); OnPropertyChangedData(e); } catch (ArgumentException) { /* nothing changed */ }","preventionTips":["Keep at least the old value when the new one is unknown (or vice versa)","Guard event construction with a both-null check","Use empty sentinels rather than null where a value is required"],"tags":["wpf","ink","argumentexception","event-args"],"backgroundTag":"null-argument","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"}