Is this possible with PropertyGrid?

Grids for WPF Forum

Posted 7 years ago by Kasper
Version: 11.1.0545
Avatar
Hi guys,

For a specific purpose, I need a control that looks a lot like your PropertyGrid, and yet I haven't found a way to get it to behave like I want it to. This control should basically show a list of parent objects with a random number of child objects for each parent object, so a category with a bunch of properties. Both category and property rows should have a checkbox in the left part, before the display name. I would prefer if I could simply bind to a collection of my parent objects and then template the content for both parent and children, but after a couple of hours of trial and error, with the documentation and sample browser constantly open, I'm not sure it can be done that way. What are my alternatives and is this even possible with PropertyGrid? If so, how?

Comments (7)

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

It certainly seems possible, but you don't really explain what the CheckBoxes are used for.

You would have to build a custom DataFactory, which would generate ICategoryDataAccessors for your parent objects and IPropertyDataAccessors for the child objects. Adding a CheckBox to the front would be different between categories and properties. For categories, you'd need to set the PropertyGridDataAccessorItem.HeaderTemplate when it's DataAccessorType is Category, which would include the CheckBox and a TextBlock that shows the display name. For properties, you can customize the name cells in the same manner as the value cells, using property editors. Our WinForms PropertyGrid Functionality demo shows how to add items to the name cell, you'd want to do something similar.


Actipro Software Support

Posted 7 years ago by Kasper
Avatar
Hi,

>It certainly seems possible, but you don't really explain what the CheckBoxes are used for.

I simply want them to enable/disable a property on the class they are bound to, as well as make a change in the user interface. Should that be problem?

I think I have already been through that demo, but I will look into it again. The whole datafactory and accessor thing is still a bit difficult for me to grasp, but I will go over it once more. If you have any more hints or advice, please don't hold back on me :)
Posted 7 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Hi Kasper,

No, you should be able to easily bind the CheckBox to the PropertyGridDataAccessorItem.IsEnabled property using a relative source binding.

The data factories are pretty straight forward. They take an array of object (which typically includes a single object) and return a list of IDataAccessors. There are three types of IDataAccessors you can return: ICategoryDataAccessor, IPropertyDataAccessor, and ICategoryEditorDataAccessor. This list is ultimately assigned to the PropertyGrid.ItemsSource property. So it's just a fancy way to generate the "data items" for the PropertyGrid.

The PropertyGridDataAccessorItem (which is equivalent to a TreeViewItem) is responsible for displaying all three types of accessors. This type is dynamically created by the PropertyGrid, just as TreeViewItem is created by the TreeView for it's items.


Actipro Software Support

Posted 7 years ago by Kasper
Avatar
Hi,

Thank you for the response and sorry for the slow response time. I'm jumping between various parts of the application :)

I have played some more with this, and I can now add both category and property editors which have a checkbox. I'm not convinced that I'm doing it the most optimal way though, but it was what I could come up with by going through documentation and sample apps. In the Resources part of the PropertyGrid, I have defined a style for category items like this:
<Style x:Key="{x:Type propgrid:PropertyGridDataAccessorItem}" TargetType="{x:Type propgrid:PropertyGridDataAccessorItem}">
    <Style.Triggers>
        <Trigger Property="DataAccessorType" Value="Category">    
....
And for properties, I have a simple DataTemplate like this:
<DataTemplate x:Key="{x:Static propgrid:BuiltinEditors.TextBlockNameTemplateKey}">
    <CheckBox Content="{Binding}"></CheckBox>
</DataTemplate>
Is that a some what decent way of doing things, or is there a better way?

Anyway, my current problem right now is that I don't know how to interact with the objects that I'm adding to the grid. For instance, if I have a property on the class that I'm adding called "IsActive", how can I access this property in the templates? And how can I access them e.g. in the Click event of the checkbox? As mentioned, I need to respond to a changed IsChecked property and update something completely different in my GUI. It seems that for categories, only a string is passed for binding. At the moment, I'm adding the items manually, like you talked about with the factory, and I can set stuff like DisplayName and Value just fine, but what I want is access to the objects that I'm currently adding.

This all seems very cumbersome though - would it not be possible to simply define a HierarchicalDataTemplate and then bind a list of my parent classes to the ItemsSource property? Please advice on what to do here :)
Posted 7 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Hi Kasper,

By adding the CheckBox to the ControlTemplate for both categories and properties, then you'd have everything in one location. But what you have is fine also.

You can use RelativeSource bindings and search for an ancestor that implements ICategoryDataAccessor or IPropertyDataAccessor and access the data that way. This can also be done in code-behind using our VisualTreeHelper.GetAncestor method.

If you are using the features on the PropertyGrid to automatically pull properties from objects, then you would not be able to use a HierarchicalDataTemplate. The HierarchicalDataTemplate defines both the DataTemplate to use for a item, as well has how bind to the child items. The latter does not work with our DataFactory architecture. Even beyond that using HierarchicalDataTemplate would short circuit our property editors, so you would have manually manage which DataTemplate is used for each item (for both the name and value cell).


Actipro Software Support

Posted 7 years ago by Kasper
Avatar
Hi,

>By adding the CheckBox to the ControlTemplate for both categories and properties, then you'd have everything in one location. But what you have is fine also.

Could you show me how to do that? I will still need to be able to use different editors for the child rows though.

>You can use RelativeSource bindings and search for an ancestor that implements ICategoryDataAccessor or IPropertyDataAccessor and access the data that way. This can also be done in code-behind using our VisualTreeHelper.GetAncestor method.

I suppose you mean the GetParent() method? Anyway, I can find the IPropertyDataAccessor, but I have honestly no idea what to do with it. It still doesn't give me access to the data I need, as far as I can tell? I tried creating my own DataAccessor class, inheriting from CachedPropertyDataAccessorBase as you do in your examples, but that one I can't seem to find with a RelativeSource. Could you please provide me with an example here? It seems very complicated and I have already spent a lot of time trying to find my way around all the interfaces and classes, with no particular luck :)

>If you are using the features on the PropertyGrid to automatically pull properties from objects, then you would not be able to use a HierarchicalDataTemplate. The HierarchicalDataTemplate defines both the DataTemplate to use for a item, as well has how bind to the child items. The latter does not work with our DataFactory architecture. Even beyond that using HierarchicalDataTemplate would short circuit our property editors, so you would have manually manage which DataTemplate is used for each item (for both the name and value cell).

Okay, I guess I won't use that approach then :)
Posted 7 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Hi Kasper,

It should be similar to how you did for the Categories above. Basically, you'd take our default Style for PropertyGridDataAccessorItem and then insert the CheckBox in the ControlTemplates defined in there. If you include that Style in your Application.Resources, then it would be picked up by all items in a PropertyGrid.


No, I don't mean GetParent. You can do something like IsChecked="{Binding Path=DataContext.Target.Someting, RelativeSource={RelativeSource AncestorType={x:Type propgrid:IPropertyDataAccessor}}". Keep in mind that the PropertyGridDataAccessorItem also implements IPropertyDataAccessor and forwards things to the IPropertyDataAccessor is wraps. The wrapped IPropertyDataAccessor is located in the DataContext, so you can access your custom IPropertyDataAccessor using that if needed (like I show).

It might be easier if you sent over a small sample project that shows what your data objects look like and how you have customized things so far. 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 14 days ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.