Best way for expanded property with value

Grids for WPF Forum

Posted 6 years ago by Tom Laverty
Version: 12.2.0571
Avatar

I'm trying to build a property editor with hierarchy where expandable nodes can also hold a property value, something like this:
- Enable Advanced Features         [ ]
         Advanced Bool Option A      [ ]
         Advanced Text Option B      [             ]

I’m currently prototyping this using a custom editor on the expandable parent, with the data type of the parent property being a class containing the properties of the children. I then deal with the binding of the parent editor value myself (with some binding issues that I need to work through).


Is this the best way? I don’t really need or want the encapsulation of the child properties being a separate class. Our business logic understands the precedence of the properties so I’m just using the expandability for the UI. Put another way - I don’t need the hierarchy mirrored in my viewmodel class.

I’m already using nested categories for some semantics so I can’t use that feature.

Is a custom factory a better approach here? Your guidance is welcomed!

Comments (6)

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

Hi Tom,

What you are already doing is one way to do things.

In our latest maintenance release we added a new "Custom Factory" QuickStart.  The CustomFactory there also shows an example of making data accessors that route from child objects.  You could possibly use that sort of concept but in reverse.  Instead of merging props from multiple source objects into a single level like in the QuickStart, you want to push out a data accessor with your custom type and then when it examines that type for expansion, you'd route your faux sub-props to data accessors at that level.


Actipro Software Support

Posted 6 years ago by Tom Laverty
Avatar

Ok, I'm trying a custom factory, looks like that will give me a flexible solution. One question: how do I create an expandable property from the factory? Right now my custom factory implements GetProperties and I can add my 'top-level' options but I have not found anything in the samples that shows me how to make my node expandable.

I've tried adding child properties using the PropertyDescriptorDataAccessor that takes a parent argument, and I've also called the addChild() method on the parent PropertyDescriptorDataAccessor but no luck.

I also see that the GetProperties seems to be called once for the main object and again for each individual property, is that where I want to pass back a list of sub-properties? (but I don't see a way do know which individual property is being queried because the 'value' param is null in these cases).

Regards,

Tom

[Modified 6 years ago]

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

Hi Tom,

Yes that's correct.  The GetProperties will be called for each node level.  If you want something to be expandable, you can put this on the object type:

[TypeConverter(typeof(ExpandableObjectConverter))]

In our sample you can see we do that on the PhoneNumbersViewModel.


Actipro Software Support

Posted 6 years ago by Tom Laverty
Avatar

FYI I ended up punting on this, I could not find  an approach that worked well for me. I tried a couple flavors of a custom factory supplying my own PropertyDescriptorDataAccessor. In one case I initialized the PropertyDescriptorDataAccessor with data that connects the expandable object with the target property, and in another I kept the PropertyDescriptorDataAccessor associated with the expandable object but provided and override for GetValue where it piped it through the the target property.

It came down to the way the propgrid control calls the GetProperties method. It works fine for the top-level properties, I can provide what I need. But when I get called to supply child properties for each of the properties I supplied at the top level I don't have the context to know if I'm dealing with one of my expandable properties or not. The arguments provided just give the 'value' and in the case of one of my expandable properties it's the target value with is usually a simple type (bool, int). I don't have the type info to know if that's one of my special cases where the property is actually the 'mapped' instance and should thus provide the list of children.

I did try some hairy schemes of keeping index data around, etc. but that was fragile (looks like GetProperties is designed for re-entrancy?) and there are also cases where GetProperties is called when mousing with the propgrid and GetProperties is expected to return the right info given an arbitrary target value param.

I also tried an approach of supplying my own DataTemplate for the my expandable nodes and doing the binding to the target property in xaml. This worked ok in some simple cases but I was not really prepared to duplicate all the templates of the built-in editors we need to get there (are your templates for the build-in's even available w/o source license?).

I also considered using my own datatypes for all my target properties that are representing an expandable category (so I could detect my 'expandable' case based on data type) but many are sealed and I didn't what to spend days to create some kind of encapsulation classes.

Am I missing something here? I tried my hand at a type converter but no luck there either (but I did not put in a whole lot of effort in that direction).

Is there some other way to provide a binding expression for an exapandable property? (xaml, code, or otherwise)

I ended up just using indents in the property display names to approximate the desired look (but I don't get expandability this way).

Regards,

Tom

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

Hi Tom,

If you are a WPF Studio customer then the default styles and template for all the controls will be downloadable from your account.  Or if you have just licensed individual products, you can email our support address to request the appropriate ones.

GetProperties will be called at certain times that the tree needs to be reconstructed and possibly in other scenarios as you saw.  I believe that the determination to know if an object is expandable is whether it has a TypeConverter that has its GetPropertiesSupported method returning true, which is what the ExpandableObjectConverter does.

One idea I haven't tried but I wonder if it would help you since you said you need to pass data down.  The options parameter in GetProperties has a ParentAccesor property on it.  Do you think you could store your contextual data on the parent accessor and then in the GetProperties call, examine that for what you need?  You are in control of what data accessors get added so you could add custom data in them somehow.


Actipro Software Support

Posted 6 years ago by Tom Laverty
Avatar

I will try using the ParentAccessor when I get a chance, that actually sounds like what I need to provide more context when GetProperties is called - thanks!

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

Add Comment

Please log in to a validated account to post comments.