Dynamicly filling values in combobox

Grids for WPF Forum

Posted 10 years ago by Martin de Jong - Statistics Netherlands
Avatar
Hi

After some help of u guys.. (and girls..?) i made a TypeConverter to show a combobox for the property StartupProject showing a list of Projects (both properties of same object Solution).
This works.
    public class ProjectStringConverter : TypeConverter {


        public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context) {
            Solution sol = ((Actipro.Primitives.PropertyDescriptorDataAccessor)(context)).Target as Solution;
            if (sol != null) {
                ArrayList al = sol.Projects.AsArrayList();
                al.Add(null);
                return new StandardValuesCollection(al);
            }
            return null;

        }
        public override bool GetStandardValuesSupported(ITypeDescriptorContext context) {
            return true;
        }
        public override bool GetStandardValuesExclusive(ITypeDescriptorContext context) {
            return true;
        }
    }
The problem arrised when the (collection of) Projects is changed. These changes do fire a NotifyChanged event, but the StandardValueCollection is not re-created. How can i invoke the re-creation of the ComboBoxStringPropertyEditor.

Regards
Martin

Comments (4)

Posted 10 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Hi Martin,

This type of behavior isn't directly supported by the native WinForms PropertyGrid, so it's not support by our PropertyGrid when using things like the TypeConverter. It can be done with our PropertyGrid, but requires a custom DataFactory and a custom IPropertyDataAccessor

The steps would be:

1. Create a class that derives from PropertyDataAccessorBase and implements the abstract members, say CustomPropertyDataAccessor. This class will reference another IPropertyDataAccessor and will forward all calls to that instance. So the constructor of this class will take an IPropertyDataAccessor that it is wrapping.

2. The only exceptions to #1 are StandardValues and StandardValuesAsStrings. Our default implementations of these properties cache the collection returned. So you need to implement it such that it will return the current collection every time (or if #3 is called, you can reset a cache of your own).

3. In the constructor of #1, you would attach to the NotifyCollectionChanged event of the Projects collection. The Target property will contain your Solution. In the event handler, you would need to call OnPropertyChanged("StandardValues") and OnPropertyChanged("StandardValuesAsStrings"). This step notifies the attached ComboBox that it's items has changed.

4. Create a class that derives from TypeDescriptorFactory or TypeReflectionFactory (depending on which one you are using).

5. Override GetProperties(object, DataFactoryOptions), which calls the base method. Your implementation will then go through the collection returned from the base method, and will wrap the IPropertyDataAccessor for "StartupProject" with an instance of #1.

6. Update your PropertyGrid.DataFactory to use an instance of #4.

You could also use attributes to make this a bit more dynamic. Meaning you could have say CustomAttribute(string associatedCollectionProperty) decorating your StartupProject, then look for that in your DataFactory/PropertyDataAccessor.

Hope this makes sense.


Actipro Software Support

Posted 10 years ago by Martin de Jong - Statistics Netherlands
Avatar
Yes, this maded sense indeed. Thank you.

I implemented all the steps you sugguested , i even made a custom property to make it dynamicly and independent of the Solution class.
I didnt need nor found the Target property but the Accessor has the collection as parameter in his constructor.
Posted 7 years ago by Jb RIGUET
Avatar

Hi, I'm trying to achieve the same thing Martin was, with only one small thing on top of that.

I have a simple ObservableCollection<string> Platforms and a reference to an item of this list, DefaultPlatform, which is selected trough a ComboBox.

I followed the steps you described above, and everything is working perfectly, except when I trigger OnPropertychanged("StandardValues") the property DefaultPlateform is reset to null. I tried to set the value in the CollectionChanged Event, but it keeps beeing reset (even if I set the value after the StandardValues are changed).

I almost get the behavior I need, but I'm stuck at this tiny detail, do you have any idea or leads I can follow ?

 

Edit : Actually, after more investigation, the value is correctly set to what i want, but the ComboBox is not reflecting the selected choice.

 

Thanks in advance,

JB.

[Modified 7 years ago]

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

Hi JB,

Have you tried calling the Refresh method on the accessor as well?  Perhaps that would help.


Actipro Software Support

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

Add Comment

Please log in to a validated account to post comments.