DynamicObject property types

5 posts, 0 answers
  1. Jerome
    Jerome avatar
    87 posts
    Member since:
    Aug 2010

    Posted 31 Jan 2013 Link to this post

    Hello. I'm trying to figure out the proper way to provide editing for a collection of name/type/value things. I was hoping to use DynamicObject, and expose dynamic properties for the properties to be edited. DynamicObject however, as far as I can tell, has no real way to expose more than a member name to consumers (such as RadPropertyGrid.) So, I don't know how to expose the TYPE of the propert to RadPropertyGrid.

    What's the best way to go about this? Is DynamicObject suitable?
  2. Ivan Ivanov
    Admin
    Ivan Ivanov avatar
    1128 posts

    Posted 05 Feb 2013 Link to this post

    Hello,

    RadPropertyGrid supports such scenarios with some minor customizations. May, I ask you to send us a small project that illustrates your business object declaration through a support ticket and I will prepare a demo project for you?

    Kind regards,
    Ivan Ivanov
    the Telerik team

    Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

  3. UI for WPF is Visual Studio 2017 Ready
  4. Chris
    Chris avatar
    18 posts
    Member since:
    Sep 2014

    Posted 06 Nov 2015 Link to this post

    Ivan,

         Could you send me the demo project as well. I am trying to do the same thing. Thank you.

  5. Ivan Ivanov
    Admin
    Ivan Ivanov avatar
    1128 posts

    Posted 11 Nov 2015 Link to this post

    Hi,

    I prepared a sample project with RadPropertyGrid with dynamic properties. You can use it as a starting point if you have any further questions.

    Regards,
    Ivan Ivanov
    Telerik
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
  6. Chris
    Chris avatar
    18 posts
    Member since:
    Sep 2014

    Posted 11 Nov 2015 in reply to Ivan Ivanov Link to this post

    Thank you Ivan.

    For anyone else that is pursuing this approach, here is the code that is working for me.

    private sealed class MyDynObject : DynamicObject, ICustomTypeDescriptor, INotifyPropertyChanged
      {
        private class OrderedProperty
        {
          public IProperty Property { get; set; }
          public int Order { get; set; }
        }
      
        private readonly Dictionary<string, OrderedProperty> dynamicProperties
          = new Dictionary<string, OrderedProperty>();
      
        public MyDynObject(ReadOnlyObservableCollection<IProperty> properties)
        {
          for (var i = 0; i < properties.Count; i++)
          {
            var property = properties[i];
            dynamicProperties.Add(property.Name, new OrderedProperty()
            {
              Property = property,
              Order = i
            });
            PropertyChangedEventManager.AddHandler(property, Property_PropertyChanged, nameof(IProperty.Value));
          }
        }
      
        private void Property_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
          if (nameof(IProperty.Value).Equals(e.PropertyName))
          {
            OnPropertyChanged(((IProperty)sender).Name);
          }
        }
      
        public override IEnumerable<string> GetDynamicMemberNames()
        {
          return dynamicProperties.Keys;
        }
      
        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
          if (dynamicProperties.ContainsKey(binder.Name))
          {
            result = dynamicProperties[binder.Name].Property.Value;
            return true;
          }
          result = null;
          return false;
        }
      
        public override bool TrySetMember(SetMemberBinder binder, object value)
        {
          if (dynamicProperties.ContainsKey(binder.Name))
          {
            dynamicProperties[binder.Name].Property.Value = value;
            OnPropertyChanged(binder.Name);
            return true;
          }
          return false;
        }
      
        #region Implementation of INotifyPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;
      
        private void OnPropertyChanged(string propertyName)
        {
          if (PropertyChanged == null)
          {
            return;
          }
      
          var eventArgs = new PropertyChangedEventArgs(propertyName);
          PropertyChanged(this, eventArgs);
        }
        #endregion
      
        #region Implementation of ICustomTypeDescriptor
        public AttributeCollection GetAttributes()
        {
          throw new NotImplementedException();
        }
      
        public string GetClassName()
        {
          return GetType().Name;
        }
      
        public string GetComponentName()
        {
          throw new NotImplementedException();
        }
      
        public TypeConverter GetConverter()
        {
          throw new NotImplementedException();
        }
      
        public EventDescriptor GetDefaultEvent()
        {
          throw new NotImplementedException();
        }
      
        public PropertyDescriptor GetDefaultProperty()
        {
          throw new NotImplementedException();
        }
      
        public object GetEditor(Type editorBaseType)
        {
          throw new NotImplementedException();
        }
      
        public EventDescriptorCollection GetEvents()
        {
          throw new NotImplementedException();
        }
      
        public EventDescriptorCollection GetEvents(Attribute[] attributes)
        {
          throw new NotImplementedException();
        }
      
        public PropertyDescriptorCollection GetProperties()
        {
          var properties = dynamicProperties
              .Select(pair => new DynamicPropertyDescriptor(this,
                  pair.Key, pair.Value.Property.ValueType, GetAttributes(pair.Value)));
          return new PropertyDescriptorCollection(properties.Cast<PropertyDescriptor>().ToArray());
        }
      
        public PropertyDescriptorCollection GetProperties(Attribute[] attributes)
        {
          throw new NotImplementedException();
        }
      
        public object GetPropertyOwner(PropertyDescriptor pd)
        {
          throw new NotImplementedException();
        }
      
        private Attribute[] GetAttributes(OrderedProperty orderedProperty)
        {
          var attributes = new Attribute[2];
          attributes[0] = new DisplayAttribute
          {
            Name = orderedProperty.Property.Name,
            Description = orderedProperty.Property.Description,
            GroupName = orderedProperty.Property.GroupName,
            Order = orderedProperty.Order
          };
          attributes[1] = new ReadOnlyAttribute(orderedProperty.Property.IsReadOnly);
          return attributes;
        }
        #endregion
      
      
      
      
        private class DynamicPropertyDescriptor : PropertyDescriptor
        {
          private readonly MyDynObject model;
      
          public DynamicPropertyDescriptor(MyDynObject model,
              string propertyName, Type propertyType, Attribute[] propertyAttributes)
              : base(propertyName, propertyAttributes)
          {
            this.model = model;
            PropertyType = propertyType;
          }
      
          public override bool CanResetValue(object component)
          {
            return true;
          }
      
          public override object GetValue(object component)
          {
            return model.dynamicProperties[Name].Property.Value;
          }
      
          public override void ResetValue(object component)
          {
          }
      
          public override void SetValue(object component, object value)
          {
            model.dynamicProperties[Name].Property.Value = value;
          }
      
          public override bool ShouldSerializeValue(object component)
          {
            return false;
          }
      
          public override Type ComponentType => typeof(MyDynObject);
      
          public override bool IsReadOnly => model.dynamicProperties[Name].Property.IsReadOnly;
      
          public override Type PropertyType { get; }
        }
      }
     
      
     
    public interface IProperty : INotifyPropertyChanged
      {
        string Name { get; }
      
        object Value { get; set; }
      
        Type ValueType { get; }
      
        string Description { get; }
      
        bool IsReadOnly { get; }
      
        string GroupName { get; }
      }
Back to Top
UI for WPF is Visual Studio 2017 Ready