Get accessor from editor

Grids for WPF Forum

Posted 10 years ago by Michael Rösslhumer
Version: 9.2.0515
Avatar
Hi is there a possibility to get access to the dataAccessor from a derived property editor?

Comments (5)

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

Yes and no. You can't get the underlying IPropertyDataAccessor from a .Net class that derives from PropertyEditor. The PropertyEditor is merely a mapping to indicate when/where the associated DataTemplates should be used. A single PropertyEditor could be applied to any number of properties.

You can however get to the underlying IPropertyDataAccessor from the DataTemplate(s) used by a PropertyEditor.

If you can explain the problem you are facing (i.e. the reason you need the IPropertyDataAccessor in the PropertyEditor), we might be able to point you in the right directly.


Actipro Software Support

Posted 10 years ago by Michael Rösslhumer
Avatar
Ok i will try to explain you my problem. I have an object of the following type

public class Father : PersonFull
    {
        public Father()
        {
            PossibleChildren = new List<PersonFull>
                                {
                                    new PersonFull() { FirstName="Julia",Surname="Mustermann"},
                                    new PersonFull() { FirstName="Verena", Surname = "Mustermann"},
                                    new PersonFull() { FirstName="Anita", Surname = "Mustermann"},
                                    new PersonFull() { FirstName="Michael", Surname = "Mustermann"},
                                    new PersonFull() { FirstName="Thomas", Surname = "Mustermann"},
                                    new PersonFull() { FirstName="Bernhard", Surname = "Mustermann"}
                                };

        }

        public IList<PersonFull> Children { get; set; }

        [Browsable(false)]
        public IList<PersonFull> PossibleChildren { get; set; }

public string Name { get; set; }
    }
I want to show this object in the property grid. For the children property i want to show an individual property editor, the property editor should look like
<Editors:PropertyEditor x:Class="ActiproSoftware.Windows.ProductSamples.PropertyGridSamples.QuickStart.Virtualization.SimpleMasterDetailEditor"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:Editors="clr-namespace:ActiproSoftware.Windows.Controls.PropertyGrid.Editors;assembly=ActiproSoftware.PropertyGrid.Wpf30"
    xmlns:Com="clr-namespace:ActiproSoftware.Windows.ProductSamples.PropertyGridSamples.QuickStart.Virtualization">
  <Editors:PropertyEditor.ValueTemplate>
    <DataTemplate>
      <StackPanel Orientation="Vertical">
      <ComboBox Background="Blue" ItemsSource="{Binding AddItems}" SelectedItem="{Binding SelectedItem}"/>
      <ListBox Background="Red" ItemsSource="{Binding AddedItems}">
        <ListBox.CommandBindings>
          <CommandBinding Command="{x:Static Com:Commands.RemoveCommand}" Executed="Remove"/>
        </ListBox.CommandBindings>
        <ListBox.ItemTemplate>
          <DataTemplate>
            <StackPanel>
              <ContentPresenter/>
              <Button Content="X" Tag="{Binding}" Command="{x:Static Com:Commands.RemoveCommand}"/>
            </StackPanel>
          </DataTemplate>
        </ListBox.ItemTemplate>
      </ListBox>
      </StackPanel>
    </DataTemplate>
  </Editors:PropertyEditor.ValueTemplate>
</Editors:PropertyEditor>
That should do the following. The Combobox should contain all available children, if a child is selected it should be added to the Children collection of the current selected object (it would be a father object, that could be found in the IPropertyDataAccessor). When the child was added to the children collection it should disappear from the combobox with the available children. It should be also possible to remove a child from the children collection, then the child should appear again in the combobox with the available children.

I thought to implement this with collection views and filters in the property editor, but for that i need access to the DataAccessor to get the current data object(father)

May you can give me some hints and code snippets to achieve this.

PS: i dont't won't to use category editors
Posted 10 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Hi Michael,

Ok, so really you just need to access the underlying object (in this case Father) from your DataTemplate. You can get to the underlying object using the IPropertyDataAccesor.Target property. If you add this to your top-level StackPanel, then the remaining elements can use simple binding statements:

DataContext="{Binding Target, RelativeSource={RelativeSource AncestorType={x:Type propgrid:IPropertyDataAccessor}}}

Note: PropertyGridDataAccessorItem implements IPropertyDataAccessor and simply forwards any calls to the "data" IPropertyDataAccessor. Because Target is explicitly implemented by PropertyGridDataAccessorItem, you may need to access the "data" IPropertyDataAccessor. To do so, you'd use this statement:

DataContext="{Binding DataContext.Target, RelativeSource={RelativeSource AncestorType={x:Type propgrid:IPropertyDataAccessor}}}

Beyond that, if you implement "observable" collections in your Father object, then the ComboBox and ListBox will automatically update as you move an item from one collection to another. WPF comes with the ObservableCollection<T>, which you can use inplace of the List<T>. If you don't want or can't reference the WPF assemblies, then you'd need to implement a derivation of List<T> that implements INotifyCollectionChanged.


Actipro Software Support

Posted 10 years ago by Michael Rösslhumer
Avatar
Ok, but what would i do, when the PossibleChildren collection is not inside the father class or one of its parents.
If the PossibleChildren collection should be part of a derived property editor, how can i access this property from the property editor xaml.
And another question, is there a way in the property editor that i can find out that the underlying dataAccessor changes. And there is really no way to find out the current data Accessor of the property editor, no hack?
Posted 10 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Hi Michael,

It is possible to access the property editor from the DataTemplate. You can also access the IPropertyDataAccessor for the DataTemplate. So you might be able to use some kind of attached behavior to tie them together.

You can pass the property editor to the DataTemplate using code similar to this in your PropertyEditor-derived class:
private DataTemplate dataTemplate;

public override DataTemplate ValueTemplate {
    get {
        if (null == this.dataTemplate) {
            FrameworkElementFactory factory = new FrameworkElementFactory(typeof(ContentPresenter));
            factory.SetValue(ContentPresenter.ContentProperty, this);
            factory.SetValue(ContentPresenter.ContentTemplateProperty, /* set to actual desired DataTemplate */);

            this.dataTemplate = new DataTemplate() { VisualTree = factory };
        }
        return this.dataTemplate;
    }
    set { /* No-op */ }
}
This will effectively set the DataContext to the PropertyEditor, which you can then using in bindings (such as PossibleChildren). This will not work if the PropertyEditor is used by more than one property though, as both would be changing the same underlying collection.

Alternatively, if you built an attached behavior you could "copy" the PossibleChildren into an attached property and keep it in sync with the Father.Children collection. You'd need three attached properties: 1 for the original PossibleChildren collection, 1 for the Father.Children collection, and 1 for the "filtered/copied" PossibleChildren collection. The latter would be dynamically created from the 2 former collections. Then you could bind to the latter in your ComboBox. This would allow you to reuse the PropertyEditor across several properties.

You could also use an attached behavior to tie the PropertyEditor to the IPropertyDataAccesor together. You'd need two attached properties: 1 for the PropertyEditor, and 1 for the IPropertyDataAccessor. When both are set you'd tie them together, when one is null you'd untie them.

These attached properties would need to be set on the ContentPresenter above or one of the elements in your DataTemplate. Something like this could be used in the code above:
factory.SetValue(MyBehavior.AttachedProperty1, this);
factory.SetBinding(MyBehavior.AttachedProperty2, new Binding("DataContext") {
    RelativeSource = new RelativeSource() { AncestorType = typeof(IPropertyDataAccessor) }
});
Or something similar could be used in the DataTemplate.

Hope this helps.


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.