PropertyGrid ExpandableCollectionConverter DisplayName

Grids for WPF Forum

Posted 2 years ago by Neil Larson
Version: 17.2.0662
Avatar

The ExpandableCollectionConverter.ListItemPropertyDescriptor.DisplayName is based on property of the object (for example - MyGridDisplayName) in the collection, and I want to bind the ExpandableCollectionConverter.ListItemPropertyDescriptor.DisplayName to theMyGridDisplayName on the object, or somehow update DisplayName after the object is edited.

Lots of possible ways to go, but I'm hoping you can point me at the best way to do this.

Thanks, 

Neil

Comments (5)

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

Hi Neil,

That can be a tad tricky, so please bear with me.  You effectively need to override the ExpandableCollectionConverter+ListItemPropertyDescriptor.DisplayName property, so you have to make a class that inherits ListItemPropertyDescriptor, then overrides the property with some appropriate value.

Next create a class that inherits ExpandableCollectionConverter and override the CreateListItemPropertyDescriptor method.  Have it return an instance of your MyListItemPropertyDescriptor class.

Finally use TypeConverterAttribute to put an instance of MyExpandableCollectionConverter on your collection property.  I think doing those steps will allow you to customize it.


Actipro Software Support

Posted 1 year ago by Neil Larson
Avatar

This works for the initial creation of the list. 

I need to force the ExpandableCollectionConverter.ListItemPropertyDescriptor.DisplayName to be reevaluated when a property object changes. I did that by placing a propertychanged handler on all the items as they are added to the ListItemPropertyDescriptor. When I get the change event how do I make the ExpandableCollectionConverter redraw that one item?

 

      private class MyListPropertyDescriptor : ExpandableCollectionConverter.ListItemPropertyDescriptor
      {
         public MyListPropertyDescriptor(System.Collections.IList list, int index, Type itemType, Attribute[] attributes, bool isCollectionReadOnly, bool isReadOnly)
            : base(list, index, itemType, attributes, isCollectionReadOnly, isReadOnly)
         {
            // lay in a property change notification that will 
            var cmd = list[index] as MultiCueAddLogicalFireOrDwellCommand;
            if(cmd != null)
            {
               cmd.PropertyChanged += Cmd_PropertyChanged;
            }
         }

         private void Cmd_PropertyChanged(object sender, PropertyChangedEventArgs e)
         {
            // WHAT DO WE DO HERE???
         }

         public override string DisplayName
         {
            get
            {
               switch (this.List[Index])
               {
                  case MultiCueAddLogicalFireOrDwellCommand mcalcmd:
                     switch (mcalcmd.FiringType)
                     {
                        case MultiCueFiringType.None:
                        case MultiCueFiringType.Fire:
                           return $"T+{mcalcmd.TimingOffset:00.000} Id: {mcalcmd.LogicalId} Cue: {mcalcmd.Cue}";
                        case MultiCueFiringType.Dwell:
                           return $"T+{mcalcmd.TimingOffset:00.000} Id: {mcalcmd.LogicalId} Cue: {mcalcmd.Cue} Dwell {mcalcmd.Dwell:0.0}";
                        case MultiCueFiringType.DMX:
                           return $"T+{mcalcmd.TimingOffset:00.000} Id: {mcalcmd.LogicalId} Cue: {mcalcmd.Cue} DMX   {mcalcmd.Dwell:0.0}";
                     }
                     break;
               }
               return this.List[Index].GetType().ToString();
            }
         }
      }
Posted 1 year ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hi Neil,

The IPropertyModel.DisplayName property gets bound directly to the TextBlock in each name cell's DataTemplate. So having your IPropertyModel raise an INotifyPropertyChanged.PropertyChanged event with "DisplayName" specified will update the UI. The TypeDescriptorFactory.GetPropertyModels method is where a PropertyDescriptorPropertyModel is created to wrap the PropertyDescriptor, and that in turn calls the virtual factory.CreatePropertyModel method.

Maybe you could override CreatePropertyModel and make a class inheriting PropertyDescriptorPropertyModel that knows how to attach to your MyListPropertyDescriptor. When it sees a MyListPropertyDescriptor passed in, it could create your PropertyDescriptorPropertyModel-based class and attach to an event so your PropertyDescriptorPropertyModel-based class could call its own NotifyPropertyChanged("DisplayName") method to let our UI know to refresh.


Actipro Software Support

The latest build of this product (v2019.1 build 0683) was released 1 month ago, which was before the next post in this thread.
Posted 29 days ago by Neil Larson
Avatar

I am successfully catching the change on the object and setting the value returned by the overridden DisplayName property, and calling RaisePropertyChanged("DisplayName") but the PART_Chrome text just does not update. It seems like the binding on the TextBlock is OneTime or needs the update source trigger set to property changed. 

Posted 29 days ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hi Neil,

We use a normal Binding (not OneTime) to DisplayName, so any changes to it should get picked up and displayed if the right IPropertyModel is notifying of the update and the DisplayName property is truly returning the new value.

If you'd like us to look, can you put together a new simple sample project that shows what you are doing and send that to our support address, referencing this thread?  Remove the bin/obj folders from the ZIP you send, and rename the .zip file extension so it doesn't get spam blocked.  Thanks!


Actipro Software Support

Add Comment

Please log in to a validated account to post comments.