Property record value is not applied in RadPropertyGrid

1 Answer 39 Views
PropertyGrid
Martin
Top achievements
Rank 1
Martin asked on 04 Mar 2025, 08:06 AM

I have a record Pitch (see below)

    [TypeConverter(typeof(PitchTypeConverter))]
    public sealed record Pitch(double MinValue, double MaxValue) : IParsable<Pitch>
    {
        public static readonly Pitch Empty = new(0, 0);

        public static Pitch Parse(string s, IFormatProvider provider) 
            => throw new NotImplementedException();
        public static bool TryParse([NotNullWhen(true)] string s, IFormatProvider provider, [MaybeNullWhen(false)] out Pitch result) 
            => throw new NotImplementedException();

        public override string ToString()
            => $"{MinValue}-{MaxValue}";
    }

As you can see , I also have a TypeConverter (currently not fully implemented, but to show the problem it is sufficient).

  public sealed class PitchTypeConverter : TypeConverter
    {
        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) 
            => base.CanConvertFrom(context, sourceType);

        public override bool CanConvertTo(ITypeDescriptorContext context, [NotNullWhen(true)] Type destinationType)
            => destinationType == typeof(string);

        public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) 
            => base.ConvertFrom(context, culture, value);

        public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
            => value?.ToString() ?? Pitch.Empty.ToString();

        public override object CreateInstance(ITypeDescriptorContext context, IDictionary propertyValues) 
            => base.CreateInstance(context, propertyValues);

        public override bool GetCreateInstanceSupported(ITypeDescriptorContext context) 
            => base.GetCreateInstanceSupported(context);

        public override bool IsValid(ITypeDescriptorContext context, object value) 
            => base.IsValid(context, value);

        public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes) 
            => base.GetProperties(context, value, attributes);

        public override bool GetPropertiesSupported(ITypeDescriptorContext context) 
            => base.GetPropertiesSupported(context);

        public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context) 
            => base.GetStandardValues(context);

        public override bool GetStandardValuesExclusive(ITypeDescriptorContext context) 
            => base.GetStandardValuesExclusive(context);

        public override bool GetStandardValuesSupported(ITypeDescriptorContext context) 
            => base.GetStandardValuesSupported(context);
    }

The Pitch lives inside a ViewModel and is correctly displayed in the RadPropertyGrid, so in that sense everthing works fine.

    [Category("Conditions")]
        [Description("Sets the minimum/maximum allowed pitch limit.")]
        public Pitch PitchLimit
        {
            get => GetProperty(Pitch.Empty);
            set => SetProperty(value);
        }

        [Category("Conditions")]
        public bool RequiresDE
        {
            get => GetProperty<bool>();
            set => SetProperty(value);
        }

 

when I now edit values in the RadPropertyGrid, the RequiresDE works when pressing enter or selecting the checkbox. It doesn't work however when I edit the value for the Pitch property. I can see that the SetProperty for RequiresDE is called, but when editing the PitchLimit the SetProperty is not called.

I honestly out of ideas to find out why the RequiresDE is called and the PitchLimit isn't.

 

Any help is appreciated.

Thanks

 

 

 

 

 

 

1 Answer, 1 is accepted

Sort by
1
Accepted
Martin Ivanov
Telerik team
answered on 06 Mar 2025, 08:34 AM

Hello Martin,

I've tested the provided code on my side and it was missing some parts of the TypeConverter and IParsable implementations. I've extended the code a bit and it seems to work as expected. You can see the modifications shown in the attached project. I hope that helps.

Regards,
Martin Ivanov
Progress Telerik

Enjoyed our products? Share your experience on G2 and receive a $25 Amazon gift card for a limited time!

Martin
Top achievements
Rank 1
commented on 06 Mar 2025, 11:43 AM

@Martin: Thanks for your help. Your example works in my case, but I have found the difference which I haven't said before.

Our RadPropertyGrid.Item is bound to an ObservableCollection<MainViewModel>


   ObservableCollection<MainViewModel> list = [
            new MainViewModel() { PitchLimit = new Pitch(1, 10), RequiresDE = true },
            ];


        this.DataContext = list;

and the PropertySetMode is set to Intersection, which we need because we need to be able to manipulate many items at once. Doing this obviously does not set the Pitch property anymore, but it does this in simple cases.

Does this help?

Martin Ivanov
Telerik team
commented on 07 Mar 2025, 10:43 AM

This happens because when you use a collection and the intersection property set mode, the data binding no longer goes through your original object. Instead a proxy that holds information for all items is created and the automatically created data bindings point to that proxy object.

To get the desired behavior, you can manually update the propety UpdatePropertySetValue method of RadPropertyGrid when the TextBox editor's Text gets changed. I've updated my project to show this suggestion.

Martin
Top achievements
Rank 1
commented on 07 Mar 2025, 01:42 PM

Thank you very much. This solved the problem.

Just for your information we have made an object (ProxyObject, derived from DynamicObject) that does this automatically. If you like, I can share some code. In the end the ProxyObject is made such that the PropertyGrid thinks its working directly wit the contained object(s). Especially in the case here, it is automatically spreading the values to the attached objects. 

Using this you don't need to attach to the FieldLoaded, because the ProxyObject acts as a regular object. So the binding would work as expected.

Just as a stimulus for improvment ;-)

 

 

Martin Ivanov
Telerik team
commented on 07 Mar 2025, 02:06 PM

I am glad to hear that you've managed to resolve the problem. As for your ProxyObject, if you can share this, I believe that it is going to be helpful for someone else that hits the same scenario. Also, we can steal some ideas for future improvements if suitable for the design of the PropertyGrid control.

Tags
PropertyGrid
Asked by
Martin
Top achievements
Rank 1
Answers by
Martin Ivanov
Telerik team
Share this question
or