This project has moved and is read-only. For the latest updates, please go here.

Custom PropertyDescriptor not getting updated in Property Grid and nullables don't all show up?

Apr 11, 2014 at 11:33 AM
Edited Apr 11, 2014 at 12:36 PM
Hey,

So we setup a custom PropertyDescriptor to work with the PropGrid and things display correctly besides Nullable Types but any values that are changed do not get passed to the actual class (GetValue and SetValue are NEVER called from the PropertyDescriptor class)

    /// <summary>
    ///  This is a dummy class that acts as a surrogate.
    /// We have to add the activated objects to this so they can be edited, and then push the values back.
    /// </summary>
    [TypeConverter(typeof(CustomObjectConverter))]
    public class SurrogateAction : Item
    {
        private readonly List<ProxyMember> _props = new List<ProxyMember>();
        private readonly Dictionary<string, object> _values = new Dictionary<string, object>();

        [OrderedCategory("Action Properties", 10)]
        [ReadOnly(true)]
        public string Name { get; set; }
        
        [Browsable(false)]
        public List<ProxyMember> Members { get { return _props; } }

        public object this[string name]
        {
            get { object val; _values.TryGetValue(name, out val); return val; }
            set { _values.Remove(name); }
        }

        private class CustomObjectConverter : ExpandableObjectConverter
        {
            public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)
            {
                var stdProps = base.GetProperties(context, value, attributes);
                var obj = value as SurrogateAction;
                var customProps = obj == null ? null : obj.Members;
                var props = new PropertyDescriptor[stdProps.Count + (customProps == null ? 0 : customProps.Count)];
                stdProps.CopyTo(props, 0);
                if (customProps == null) return new PropertyDescriptorCollection(props);

                var index = stdProps.Count;
                foreach (var prop in customProps)
                {
                    props[index++] = new CustomPropertyDescriptor(prop);
                }
                return new PropertyDescriptorCollection(props);
            }
        }
        private class CustomPropertyDescriptor : PropertyDescriptor
        {
            private readonly ProxyMember _prop;
            public CustomPropertyDescriptor(ProxyMember prop)
                : base(prop.Name, null)
            {
                this._prop = prop;
            }
            public override string Category { get { return "Action Properties"; } }
            public override string Description { get { return _prop.Description; } }
            public override string Name { get { return _prop.Name; } }
            public override bool ShouldSerializeValue(object component) { return ((SurrogateAction)component)[_prop.Name] != null; }
            public override void ResetValue(object component) { ((SurrogateAction)component)[_prop.Name] = null; }
            public override bool IsReadOnly { get { return false; } }
            public override Type PropertyType { get { return _prop.Type; } }
            public override bool CanResetValue(object component) { return true; }
            public override Type ComponentType { get { return typeof(SurrogateAction); } }
            public override void SetValue(object component, object value) { ((SurrogateAction)component)[_prop.Name] = value; }
            public override object GetValue(object component) { return ((SurrogateAction)component)[_prop.Name] ?? _prop.DefaultValue; }
        }
    }
and the Proxy is just
public class ProxyMember
    {
        public string Name { get; set; }
        public string Description { get; set; }
        public object DefaultValue { get; set; }
        public Type Type { get; set; }
    }
IF I change a value in the grid and then check the value in the code, like I said, the object itself doesn't get the update and only the control (textbox, checkbox etc.) gets it for some reason. Is there something that we can do to finish this hook up or is this one of those "only possible in the paid" things? I've thought about just having to pull the value back out of the grid which seems like a bigger hassle than if I just missed something makes it not hook up correctly to make
public override void SetValue(object component, object value) { ((SurrogateAction)component)[_prop.Name] = value; }
Thanks,

Travis
Apr 15, 2014 at 10:57 AM
Any information I can get on this? I've tried quite a few different ways with ICustomTypeDescriptors and PropertyDescriptors and none of them work with the propertygrid. Am I missing something or is it only a Paid feature?
Developer
Apr 15, 2014 at 6:32 PM
Hi,

You can try the "LiveExplorer App" available on this page : https://wpftoolkit.codeplex.com/ to test the different scenarios and to know what options are available in the "Plus" version and which ones are available in the Regular version.

If you still have a problem, can you provide a complete sample, including the xaml, the propertyGrid, the sources..., so we can try to reproduce the exact same problem ?

Thank you.