title: 'Binding Builder' not interrogating nested ICustomTypeDescriptor (path empty)?
body: <p>I'm experimenting with the <code>ICustomTypeDescriptor</code> interface and the <code>PropertyDescriptor</code> class in-order to create dynamic properties on objects. I am having a lot of success with simple objects, but I cannot get nested objects to create their dynamic properties?</p>
  
  <p>For example in the data-binding dialog below, I'm adding my Person class as a <code>StaticResource</code>, then trying to data-bind the <code>Person.Child.Name</code> to a testbox:  </p>
  
  <p><img src="https://i.imgur.com/dZGL3.png"></p>
  
  <p>For the <code>Person.Child</code> I am expecting to see my dynamically created properties (<code>Name</code> and <code>Age</code>), but as you can see it's not working as expected?
  It's almost as if the databinding dialog is not interrogating the <code>ICustomTypeDescriptor</code> interface on the <code>Person.Child</code>?</p>
  
  <p>Any guidance on how to make these nested properties 'visible'?</p>
  
  <p><strong>Outer class</strong>  </p>
  
  <pre><code>public class Person : ICustomTypeDescriptor, INotifyPropertyChanged
  {
      private readonly List&lt;CustomPropertyDescriptor&gt; propertyDescriptors = new List&lt;CustomPropertyDescriptor&gt;();
      private readonly Dictionary&lt;string, object&gt; properties = new Dictionary&lt;string, object&gt;();
  
      public Person()
      {
          // 'Dynamic' Property
          string name = "Name";
          object value = "Person's Name";
          this.properties.Add(name, value);
          var propertyDescriptor = new CustomPropertyDescriptor(
              typeof(Person), 
              name, 
              value, 
              value.GetType().GetCustomAttributes(true).Cast&lt;Attribute&gt;().ToArray());
          this.propertyDescriptors.Add(propertyDescriptor);
  
          // 'Dynamic' Property
          name = "Child";
          value = new Child();
          this.properties.Add(name, value);
          propertyDescriptor = new CustomPropertyDescriptor(
              typeof(Child),
              name,
              value,
              value.GetType().GetCustomAttributes(true).Cast&lt;Attribute&gt;().ToArray());
          this.propertyDescriptors.Add(propertyDescriptor);
  
          propertyDescriptor.PropertyChanged += this.PropertyDescriptorPropertyChanged;
      }
  
      public event PropertyChangedEventHandler PropertyChanged;
  
      // Test Property (shouldn't be visible)
      public string NotDynamic { get; set; }
  
      public override string ToString()
      {
          return string.Format("{0} ({1})", this.properties["Name"], this.properties["Age"]);
      }
  
      public AttributeCollection GetAttributes()
      {
          return TypeDescriptor.GetAttributes(this, true);
      }
  
      public string GetClassName()
      {
          return TypeDescriptor.GetClassName(this, true);
      }
  
      public string GetComponentName()
      {
          return TypeDescriptor.GetComponentName(this, true);
      }
  
      public TypeConverter GetConverter()
      {
          return TypeDescriptor.GetConverter(this, true);
      }
  
      public EventDescriptor GetDefaultEvent()
      {
          return TypeDescriptor.GetDefaultEvent(this, true);
      }
  
      public PropertyDescriptor GetDefaultProperty()
      {
          try
          {
              return this.propertyDescriptors.First();
          }
          catch (InvalidOperationException)
          {
              return null;
          }
      }
  
      public object GetEditor(Type editorBaseType)
      {
          return TypeDescriptor.GetEditor(this, editorBaseType, true);
      }
  
      public EventDescriptorCollection GetEvents(Attribute[] attributes)
      {
          return TypeDescriptor.GetEvents(this, attributes, true);
      }
  
      public EventDescriptorCollection GetEvents()
      {
          return TypeDescriptor.GetEvents(this, true);
      }
  
      public PropertyDescriptorCollection GetProperties(Attribute[] attributes)
      {
          return new PropertyDescriptorCollection(this.propertyDescriptors.ToArray());
      }
  
      public PropertyDescriptorCollection GetProperties()
      {
          return this.GetProperties(null);
      }
  
      public object GetPropertyOwner(PropertyDescriptor pd)
      {
          return this;
      }
  
      protected void OnPropertyChanged(string name)
      {
          if (this.PropertyChanged != null)
          {
              this.PropertyChanged(this, new PropertyChangedEventArgs(name));
          }
      }
  
      private void PropertyDescriptorPropertyChanged(object sender, PropertyChangedEventArgs e)
      {
          this.OnPropertyChanged(e.PropertyName);
      }
  }
  </code></pre>
  
  <p><strong>Inner class</strong>  </p>
  
  <pre><code>[TypeConverter(typeof(ExpandableObjectConverter))]
  public class Child : ICustomTypeDescriptor, INotifyPropertyChanged 
  {
      private readonly List&lt;CustomPropertyDescriptor&gt; propertyDescriptors = new List&lt;CustomPropertyDescriptor&gt;();
      private readonly Dictionary&lt;string, object&gt; properties = new Dictionary&lt;string, object&gt;();
  
      public Child()
      {
          // 'Dynamic' Property
          string name = "Name";
          object value = "Person's Child";
          this.properties.Add(name, value);
          var propertyDescriptor = new CustomPropertyDescriptor(
              typeof(Person),
              name,
              value,
              value.GetType().GetCustomAttributes(true).Cast&lt;Attribute&gt;().ToArray());
          propertyDescriptor.PropertyChanged += this.PropertyDescriptorPropertyChanged;
          this.propertyDescriptors.Add(propertyDescriptor);
      }
  
      public event PropertyChangedEventHandler PropertyChanged;
  
      // Test Property (shouldn't be visible)
      public string NotDynamic { get; set; }
  
      public override string ToString()
      {
          return string.Format("{0} ({1})", this.properties["Name"], this.properties["Age"]);
      }
  
      public AttributeCollection GetAttributes()
      {
          return TypeDescriptor.GetAttributes(this, true);
      }
  
      public string GetClassName()
      {
          return TypeDescriptor.GetClassName(this, true);
      }
  
      public string GetComponentName()
      {
          return TypeDescriptor.GetComponentName(this, true);
      }
  
      public TypeConverter GetConverter()
      {
          return TypeDescriptor.GetConverter(this, true);
      }
  
      public EventDescriptor GetDefaultEvent()
      {
          return TypeDescriptor.GetDefaultEvent(this, true);
      }
  
      public PropertyDescriptor GetDefaultProperty()
      {
          try
          {
              return this.propertyDescriptors.First();
          }
          catch (InvalidOperationException)
          {
              return null;
          }
      }
  
      public object GetEditor(Type editorBaseType)
      {
          return TypeDescriptor.GetEditor(this, editorBaseType, true);
      }
  
      public EventDescriptorCollection GetEvents(Attribute[] attributes)
      {
          return TypeDescriptor.GetEvents(this, attributes, true);
      }
  
      public EventDescriptorCollection GetEvents()
      {
          return TypeDescriptor.GetEvents(this, true);
      }
  
      public PropertyDescriptorCollection GetProperties(Attribute[] attributes)
      {
          return new PropertyDescriptorCollection(this.propertyDescriptors.ToArray());      
      }
  
      public PropertyDescriptorCollection GetProperties()
      {
          return this.GetProperties(null);
      }
  
      public object GetPropertyOwner(PropertyDescriptor pd)
      {
          return this;
      }
  
      protected void OnPropertyChanged(string name)
      {
          if (this.PropertyChanged != null)
          {
              this.PropertyChanged(this, new PropertyChangedEventArgs(name));
          }
      }
  
      private void PropertyDescriptorPropertyChanged(object sender, PropertyChangedEventArgs e)
      {
          this.OnPropertyChanged(e.PropertyName);
      }
  }
  </code></pre>
  
  <p><strong>Property Descriptor</strong>  </p>
  
  <pre><code>public class CustomPropertyDescriptor : PropertyDescriptor, INotifyPropertyChanged
  {
      private readonly Type componentType;
      private string name;
      private object value;
  
      public CustomPropertyDescriptor(Type componentType, string name, object value, Attribute[] attributes)
          : base(name, attributes)
      {
          this.componentType = componentType;
          this.name = name;
          this.value = value;
      }
  
      public event PropertyChangedEventHandler PropertyChanged;
  
      public override bool IsBrowsable
      {
          get
          {
              return true;
          }
      }
  
      public override Type ComponentType
      {
          get { return this.componentType; }
      }
  
      public override bool IsReadOnly
      {
          get { return false; }
      }
  
      public override Type PropertyType
      {
          get { return this.value.GetType(); }
      }
  
      public override object GetValue(object component)
      {
          return this.value;
      }
  
      public override bool CanResetValue(object component)
      {
          return false;
      }
  
      public override void ResetValue(object component)
      {
      }
  
      public override void SetValue(object component, object value)
      {
          this.value = value;
          this.OnPropertyChanged(this.Name);
      }
  
      public override bool ShouldSerializeValue(object component)
      {
          return false;
      }
  
      private void OnPropertyChanged(string name)
      {
          if (this.PropertyChanged != null)
          {
              this.PropertyChanged(this, new PropertyChangedEventArgs(name));
          }
      }
  }
  </code></pre>