{"record":{"id":"9428547eb50e2484","repo":"PrismLibrary/Prism","slug":"tried-to-subscribe-to-propertychanged-in-the-object-that","errorCode":null,"errorMessage":"Tried to subscribe to PropertyChanged in the object that defines the '{propObserverNodeRoot.PropertyInfo.Name}' property, but the object does not implement INotifyPropertyChanged.","messagePattern":"Tried to subscribe to PropertyChanged in the object that defines the '(.+?)' property, but the object does not implement INotifyPropertyChanged\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Prism.Core/Commands/PropertyObserver.cs","lineNumber":53,"sourceCode":"            }\n\n            if (propertyExpression is not ConstantExpression constantExpression)\n                throw new NotSupportedException(\"Operation not supported for the given expression type. \" +\n                                                \"Only MemberExpression and ConstantExpression are currently supported.\");\n\n            var propObserverNodeRoot = new PropertyObserverNode(propNameStack.Pop(), _action);\n            PropertyObserverNode previousNode = propObserverNodeRoot;\n            foreach (var propName in propNameStack) // Create a node chain that corresponds to the property chain.\n            {\n                var currentNode = new PropertyObserverNode(propName, _action);\n                previousNode.Next = currentNode;\n                previousNode = currentNode;\n            }\n\n            object? propOwnerObject = constantExpression.Value;\n\n            if (propOwnerObject is not INotifyPropertyChanged inpcObject)\n                throw new InvalidOperationException(\"Tried to subscribe to PropertyChanged in the object that \" +\n                                                    $\"defines the '{propObserverNodeRoot.PropertyInfo.Name}' property, but the object does not implement INotifyPropertyChanged.\");\n\n            propObserverNodeRoot.SubscribeListenerFor(inpcObject);\n        }\n\n        /// <summary>\n        /// Observes a property that implements INotifyPropertyChanged, and automatically calls a custom action on \n        /// property changed notifications. The given expression must be in this form: \"() => Prop.NestedProp.PropToObserve\".\n        /// </summary>\n        /// <param name=\"propertyExpression\">Expression representing property to be observed. Ex.: \"() => Prop.NestedProp.PropToObserve\".</param>\n        /// <param name=\"action\">Action to be invoked when PropertyChanged event occurs.</param>\n        internal static PropertyObserver Observes<T>(Expression<Func<T>> propertyExpression, Action action)\n        {\n            return new PropertyObserver(propertyExpression.Body, action);\n        }\n    }\n}\n","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/PrismLibrary/Prism/blob/358118cd640d9a22ff8cf21c8ad197fa038b7990/src/Prism.Core/Commands/PropertyObserver.cs#L35-L71","documentation":"The root of the property chain expression must be a constant (a concrete object instance) that implements INotifyPropertyChanged; otherwise change notifications cannot be observed. When the constant root object does not implement INotifyPropertyChanged, PropertyObserver throws this InvalidOperationException.","triggerScenarios":"Calling PropertyObserver.Create(() => plainPocoObject.Property) where plainPocoObject is a constant reference but its class lacks INotifyPropertyChanged.","commonSituations":"Observing properties on plain POCO/model classes, static objects, or DTOs that were never wired for change notification.","solutions":["Make the root object's class implement INotifyPropertyChanged","Base the root object on Prism's ObservableObject/BindableBase","Observe the property on a different object that does raise change notifications"],"exampleFix":"// before\nclass Settings { public string Name { get; set; } }\n// after\nclass Settings : BindableBase { private string _name; public string Name { get => _name; set => SetProperty(ref _name, value); } }","handlingStrategy":"type-guard","validationCode":"var root = ((ConstantExpression)((LambdaExpression)expr).Body).Value;\nbool ok = root is INotifyPropertyChanged;\n// only observe roots implementing INotifyPropertyChanged","typeGuard":"static bool IsObservableRoot<T>(Expression<Func<T>> e) => e.Body is ConstantExpression c && c.Value is INotifyPropertyChanged;","tryCatchPattern":"try { PropertyObserver.Create(expr).Subscribe(); }\ncatch (InvalidOperationException) { /* root lacks INPC — subscribe manually or fix the model */ }","preventionTips":["Make all root objects of observed chains implement INotifyPropertyChanged","Prefer BindableBase for view-models used in property observers","Never observe plain POCO/DTO properties expecting change notifications"],"tags":["prism","propertyobserver","inotifypropertychanged"],"backgroundTag":"missing-dependency","analyzedSha":"358118cd640d9a22ff8cf21c8ad197fa038b7990","analyzedAt":"2026-09-15T15:00:31.079Z","contentChangedAt":"2026-09-15T15:00:31.079Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}