modified property item

Grids for WPF Forum

Posted 7 years ago by Mary Fontana - Rudolph Technologies
Avatar
Are modified property items displayed in bold only if they differ from default value?

I am using property grid to modify a set of objects.
But when the object is first displayed I would like none of the items in bold.
I would like property items displayed in bold only if they differ from when initially displayed.

If the object is saved then I would reset all items so that the modified flag is false.

Is there a way to set the default value of the properties the properties initial value?

Comments (6)

Posted 7 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Hi Mary,

Technically the properties are shown in bold if the IPropertyDataAccessor.IsModified returns true. The default implementation calls the ShouldSerializeValue method of the associated PropertyDescriptor. There are a few concrete implementations of PropertyDescriptor, so each can be a bit different.

If you are dealing with CLR properties (i.e. not WPF dependency properties), then the PropertyDescriptor will check two things. First it compares the property's value with it's "default value" using the Object.Equals method. The default value comes from the DefaultAttribute. This is generally statically defined, but there are a few ways to make it dynamic.

Next it will look for a ShouldSerializeMyProperty method (assuming your property is named MyProperty) on your object. The name is a bit confusing, but this effecitvely says if MyProperty has changed (and thus needs to be saved). More information can be found here.

So you could implement ShouldSerialize* for your properties. You'd need to save the "initial" value and only return true if it's changed. The problem with this approach is the ShouldSerialize methods also affect any .NET serializers (binary or XML) and embeds the view logic in the object.

The only other alternative would be to:

1. Create a custom DataFactory that derives from TypeDescriptorFactory (i.e. MyDataFactory).
2. Create a custom class that derives from PropertyDescriptorDataAccessor (i.e. MyPropertyDescriptorDataAccessor).
3. Create a constructor on MyPropertyDescriptorDataAccessor that matches the PropertyDescriptorDataAccessor main constructor. Such as:
public MyPropertyDescriptorDataAccessor(IPropertyDataAccessor parent, object target, PropertyDescriptor propertyDescriptor)
    : base(parent, target, propertyDescriptor) {
    // No-op
}
4. Override the MyDataFactory.CreatePropertyDataAccessor and return instances of your MyPropertyDescriptorDataAccessor and do not call teh base implementation.

5. In your MyPropertyDescriptorDataAccessor you'd want to add a Boolean field (i.e. isModified) and override the IsModifiedInternal property to return the value of that field.

6. Override the OnValueChanged method in your MyPropertyDescriptorDataAccessor and set your isModified field to true, then call the base implementation.

You may need to override the ValueInternal and ValueAsStringInternal properties instead, if OnValueChanged is called to often. Since OnValueChanged can be used to refresh the UI, even if the property's value has not changed. If you have to override the properties, then you'd need to set isModified in the setters, but otherwise call the base implementation.

7. Then you'd need to need set the PropertyGrid.DataFactory to an instance of your MyDataFactory.


Actipro Software Support

Posted 7 years ago by Mary Fontana - Rudolph Technologies
Avatar
I added your solutions with the MyPropertyDescriptorDataAccessor and MyDataFactory.

The property values starts out not being bold.
But when changed, field is not set to bold.
I know my _isModified field is getting set to true.
However it doesn't change the property item display value to bold.

I tried adding OnPropertyChanged("IsModified") but this did not change display.

If I initially set _isModified to true (The property item will be bold).
But if set later in one of the override methods, change is not seen.

Here are my override methods:


private bool _isModified = false;

        protected override bool IsModifiedInternal
        {
            get
            {
                return _isModified;
            }
        }


        public override void OnValueChanged()
        {
            _isModified = true;
          //  OnPropertyChanged("IsModified");
            base.OnValueChanged();
        }
/*
        protected override string ValueAsStringInternal
        {
            get
            {
                return base.ValueAsStringInternal;
            }
            set
            {
                _isModified = true;
                //  OnPropertyChanged("IsModified");
                base.ValueAsStringInternal = value;
            }
        }

        protected override object ValueInternal
        {
            get
            {
                return base.ValueInternal;
            }
            set
            {
                _isModified = true;
           //       OnPropertyChanged("IsModified");
                base.ValueInternal = value;
            }
        }
     */   

After I get this working, my next question is how/when to set my _isModifield to false after I do a save on the object.

Thanks in advance for your help.

[Modified at 10/12/2011 10:03 AM]
Posted 7 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Hi Mary,

As an optimization, the previous value is cached by the CachedPropertyDataAccessorBase class. So you'd need to call the OnIsModifiedChanged method so the CachedPropertyDataAccessorBase class knows to requery the IsModifiedInternal property (this is a deferred operation though, so it will only call it if needed). The OnIsModifiedChanged should technically be called for after ValueAsStringInternal and ValueInternal are called.

If you can please put together a small sample project that reproduces your issue and email it over then we can take a closer look. Be sure to remove any executables or change the extension of the zip file to ensure it gets past our email filters.

In order to reset _isModified, you'd probably have to iterate over the items in the ItemsSource collection, cast the property accessors to your custom type, and then call a method on there to reset _isModified to false.


Actipro Software Support

Posted 7 years ago by Mary Fontana - Rudolph Technologies
Avatar
Property items are bold after they are modified. It wasn't working for a combobox field I have because of changes I made to do dynamic combobox. There is a topic on this where you create custom classes for PropertyDataAccessor and TypeDescriptorFactory.
For now I changed the property item to use DialogTextBoxPropertyEditor instead.
Posted 7 years ago by Mary Fontana - Rudolph Technologies
Avatar
If you see code above where I have custom PropertyDescriptorDataAccessor
I have the following method so that an property item value cell is bold when the property is modified.

  protected override string ValueAsStringInternal
        {
            get
            {
                return base.ValueAsStringInternal;
            }
            set
            {
                base.ValueAsStringInternal = value;
                _isModified = true;
                OnIsModifiedChanged();
                
            }
        }

I get an unhandled exception when calling base.ValueAsStringInternal, if my property item is of type int and I enter in a string of letters. (value is not valid for int32 error )
If I take this method out I get the default validation - with cell border in red.
How do I get the default validation in above code.

Thanks,
Mary

[Modified at 10/30/2011 10:46 AM]
Posted 7 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Hi Mary,

It's hard to tell without seeing it in action. There doesn't appear to be anything in our code that could cause such a problem. If you can please put together a small sample project that reproduces your issue and email it over then we can take a closer look. Be sure to remove any executables or change the extension of the zip file to ensure it gets past our email filters.


Actipro Software Support

The latest build of this product (v2018.1 build 0675) was released 7 days ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.