OnValueChanged not fires for property

Grids for WPF Forum

Posted 5 years ago by Sasha
Version: 14.2.0611
Avatar

Hi,

I have a customFactory like in example. My customPropertyDataAccessor class overrides OnValueChanged() to set visibility during runtime(like in Selective Visibility example). Here is customPropertyDataAccessor class:

 private bool _isVisible;
        
 private void UpdateIsVisible()
 {
     var propertyVisibility = Target as IPropertyVisibility;
     IsVisible = propertyVisibility == null || propertyVisibility.GetPropertyVisibility(ValueName);
 }

 public bool IsVisible
 {
     get { return _isVisible; }
     private set
     {
         if (_isVisible == value) return;
             _isVisible = value;
             OnPropertyChanged("IsVisible");
     }
 }

 public override void OnValueChanged()
 {
     base.OnValueChanged();
     UpdateIsVisible();
 }

And here are two properties in my viewModel:

 public bool Offline
 {
     get { return UserControl1 != null && UserControl1.Offline; }
     set
     {
         if (UserControl1 == null) return;
         UserControl1.Offline = value;
         RaisePropertyChanged();
 	 // Force visibility to be updated
         RaisePropertyChanged("OfflineId");
     }
 }

 public int OfflineId
 {
     get { return UserControl1 != null ? UserControl1.OfflineId : 0; }
     set
     {
         if (UserControl1 == null) return;
         UserControl1.OfflineId = value;
         RaisePropertyChanged();
     }
 }

  I am using BuiltinEditors.CheckBoxValueTemplateKey in my customFactory for the property Offline and BuiltinEditors.DynamicStringValueTemplateKey for the property OfflineId.

Style for visibility:

<Style TargetType="{x:Type propgrid:PropertyGridDataAccessorItem}">
    <Style.Triggers>  
        <Trigger Property="DataAccessorType" Value="Property">
            <Setter Property="Visibility" Value="{Binding RelativeSource={RelativeSource Self}, Path=DataContext.IsVisible, Converter={StaticResource BooleanToVisibilityConverter}}" />
        </Trigger>
    </Style.Triggers>
</Style>

 My goal is to make OfflineId visible only when Offline is true. But when I change Offline's state, overriden OnValueChanged() fires only for the property Offline, and not fires for the OfflineId.

Any ideas what I have done wrong?

Comments (3)

Posted 5 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hello Sasha,

Overall your code looks very similar to our sample, and I'm not seeing anything that stands out as wrong.  It's working in our sample so I would suggest you do some in depth comparison of the differences between the two.  Maybe even clone our sample again and start making minor tweaks towards your code to see when things start to go wrong.


Actipro Software Support

Posted 5 years ago by Sasha
Avatar

Thank you for your advice. I think I found what's wrong. In my customPropertyDataAccessor there is inheritance issue: we are building propertyGrid with customFactory(customFactory example) and inheriting CachedPropertyDataAccessorBase class. When I changed customPropertyDataAccessor to inherit from PropertyDescriptorDataAccessor then everything works. I did not find an suitable interface. Can you give me an idea how can I solve this?

Answer - Posted 5 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Whenever you access a property (like Category) on CachedPropertyDataAccessorBase, it will retrieve the value the first time from its CategoryInternal property and set a flag that the value has been retrieved.  From that point on, it will not call CategoryInternal again.  This keeps performance high since the value is cached.

Each property on CachedPropertyDataAccessorBase has its own internal flag that can get set once its value has been retrieved.  Some methods like OnIsModifiedChanged for instance, will reset the flag for the IsModified property's flag, allowing the next call to IsModified to retrieve a fresh value.  Similar for OnValueChanged, which clears the flag for Value and ValueAsString.

PropertyDescriptorDataAccessor inherits CachedPropertyDataAccessorBase but attaches to the PropertyDescriptor's value changed event and in response to that event, will call the data accessor's Refresh(PropertyRefreshReason.ValueChanged) method, which ends up calling OnValueChanged and clearing the cache flag for the value.  That's likely why you see the value updating there, since OnValueChanged gets called to clear the cache flag as the property descriptor tells us the value changed.


Actipro Software Support

The latest build of this product (v2019.1 build 0683) was released 1 month ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.