title: Is it possible to have a usercontrol in WPF receive notification that a (multiple) property on a binded class has changed?
body: <p>I have a usercontrol that uses several properties on a binded class.  I would like to update the control if any of the properties on this class change. </p>
  
  <p>INotifyPropertyChanged only works if I bind to the property directly.  (this will work but I would have to bind to several properties for each instance of the control)</p>
  
  <p>Below is a striped down version of the issue I am having.  The DirectProperty works as expected.  The ParentPropertyChangedCallback() is only fired when the ParentClass is assigned to the user control, not when any of the properties change.</p>
  
  <p>Please tell me I doing something stupid =)</p>
  
  <p>UserControl1.xaml.cs</p>
  
  <pre><code>public partial class UserControl1
  {
      public static readonly DependencyProperty DirectPropertyProperty =
          DependencyProperty.Register(
             "DirectProperty",
             typeof(bool),
             typeof(UserControl1),
             new PropertyMetadata(default(bool), DirectPropertyChangedCallBack));
  
      public static readonly DependencyProperty ParentClassProperty =
          DependencyProperty.Register(
              "ParentClass",
              typeof(ParentClass),
              typeof(UserControl1),
              new PropertyMetadata(default(ParentClass), ParentPropertyChangedCallback));
  
      public UserControl1()
      {
          InitializeComponent();
      }
  
      public bool DirectProperty
      {
          get { return (bool)GetValue(DirectPropertyProperty); }
          set { SetValue(DirectPropertyProperty, value); }
      }
  
      public ParentClass ParentClass
      {
          get { return (ParentClass)GetValue(ParentClassProperty); }
          set{ SetValue(ParentClassProperty, value); }
      }
      // private void parentProperty_Changed(object)
      private static void DirectPropertyChangedCallBack(
          DependencyObject dependencyObject,
          DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
      {
          var sourceObject = dependencyObject as UserControl1;
          if (sourceObject == null) return;
  
          //set rectangle 1 base on Direct Property
          sourceObject.Rectangle1.Fill =
              sourceObject.ParentClass.DirectProperty
                  ? new SolidColorBrush(Colors.Green)
                   : new SolidColorBrush(Colors.Red);
      }
  
      private static void ParentPropertyChangedCallback(
          DependencyObject dependencyObject,
          DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
      {
          var sourceObject = dependencyObject as UserControl1;
          if (sourceObject == null) return;
  
          //set rectangle 2 base on ParentClass Property
          sourceObject.Rectangle2.Fill =
              sourceObject.ParentClass.ParentProperty
                  ? new SolidColorBrush(Colors.Green)
                  : new SolidColorBrush(Colors.Red);
  
          //set rectangle 3 base on ChildClass Property
          sourceObject.Rectangle3.Fill =
              sourceObject.ParentClass.ChildClass.ChildProperty
                  ? new SolidColorBrush(Colors.Green)
                  : new SolidColorBrush(Colors.Red);
  
      }
  }
  </code></pre>
  
  <p>ParentClass.cs</p>
  
  <pre><code>public class ParentClass :INotifyPropertyChanged
  {
      private ChildClass _childClass;
      private bool _directProperty;
      private bool _parentProperty;
      public event PropertyChangedEventHandler PropertyChanged;
  
      public ChildClass ChildClass
      {
          get { return _childClass; }
          set
          {
              if (Equals(value, _childClass)) return;
              _childClass = value;
              OnPropertyChanged();
          }
      }
      public bool DirectProperty
      {
          get { return _directProperty; }
          set
          {
              if (value.Equals(_directProperty)) return;
              _directProperty = value;
              OnPropertyChanged();
          }
      }
  
      public bool ParentProperty
      {
          get { return _parentProperty; }
          set
          {
              if (value.Equals(_parentProperty)) return;
              _parentProperty = value;
              OnPropertyChanged();
          }
      }
      [NotifyPropertyChangedInvocator]
      protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
      {
          var handler = PropertyChanged;
          if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
      }
  }
  </code></pre>
  
  <p>ChildClass.cs</p>
  
  <pre><code>public class ChildClass : INotifyPropertyChanged
  {
      private bool _childProperty;
      public event PropertyChangedEventHandler PropertyChanged;
  
      public bool ChildProperty
      {
          get { return _childProperty; }
          set
          {
              if (value.Equals(_childProperty)) return;
              _childProperty = value;
              OnPropertyChanged();
          }
      }
  
      [NotifyPropertyChangedInvocator]
      protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
      {
          var handler = PropertyChanged;
          if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
      }
  }
  </code></pre>
  
  <p>**** Working Modified ParentClass</p>
  
  <pre><code>public class ParentClass :INotifyPropertyChanged
  {
      private ChildClass _childClass;
      private bool _directProperty;
      private bool _parentProperty;
      public event PropertyChangedEventHandler PropertyChanged;
  
  
      public ParentClass()
      {
          PropertyChanged += OnPropertyChanged;
      }
  
      public ChildClass ChildClass
      {
          get { return _childClass; }
          set
          {
              if (Equals(value, _childClass)) return;
              _childClass = value;
              OnPropertyChanged();
              _childClass.PropertyChanged += OnPropertyChanged;
              DirectProperty = !DirectProperty;
          }
      }
      public bool DirectProperty
      {
          get { return _directProperty; }
          set
          {
              if (value.Equals(_directProperty)) return;
              _directProperty = value;
              OnPropertyChanged();
          }
      }
  
      public bool ParentProperty
      {
          get { return _parentProperty; }
          set
          {
              if (value.Equals(_parentProperty)) return;
              _parentProperty = value;
              OnPropertyChanged();
              DirectProperty = ! DirectProperty;
          }
      }
      [NotifyPropertyChangedInvocator]
      protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
      {
          var handler = PropertyChanged;
          if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
      }
      private void OnPropertyChanged(object sender, PropertyChangedEventArgs propertyChangedEventArgs)
      {
          if (propertyChangedEventArgs.PropertyName == "DirectProperty") return;
          // Properties that are bound to the UI you want to update
          DirectProperty = ! DirectProperty;
      }
  }
  </code></pre>