This is a migrated thread and some comments may be shown as answers.

Solution: easy 'PreventNesingAttribute' implementation for separate properties

0 Answers 10 Views
PropertyGrid
This is a migrated thread and some comments may be shown as answers.
Art
Top achievements
Rank 1
Art asked on 19 Feb 2017, 08:01 PM

Hello! I found this discussion. 08 Oct 2014 Yoan says:

"I am afraid that this functionality is not supported since there are some conceptual impediments that prevent us to change the implementation of RadPropertyGrid. However, I have logged this in our system as feature request..."

Anyway, I spent a couple of hours and just put it here. All we need is:

  1. ControlTemplate of the PropertyGridFieldTemplate, defined in ResourceDictionary (Theme);
  2. NestedPropertyVisibilityBehavior
  3. PreventNestingAttribute

In the ControlTemplate find "PART_NestedPropertiesButton" and replace it with

<t:RadToggleButton x:Name="PART_NestedPropertiesButton"
        Style="{StaticResource PropertyGridNestedToggleButtonStyle}"
        Background="Transparent"
        Width="25"
        IsChecked="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IsExpanded, Mode=TwoWay}">
    <i:Interaction.Behaviors>
        <behaviors:NestedPropertyVisibilityBehavior PropertyGridField="{Binding RelativeSource={RelativeSource TemplatedParent}}"
 ShouldDisplayNestedProperties="{Binding ShouldDisplayNestedProperties, RelativeSource={RelativeSource TemplatedParent}}"/>
    </i:Interaction.Behaviors>
</t:RadToggleButton>

 

Behavior class:

public class NestedPropertyVisibilityBehavior : Behavior<RadToggleButton>
{
    public static readonly DependencyProperty PropertyGridFieldProperty =
        DependencyProperty.Register("PropertyGridField", typeof (PropertyGridField),
            typeof (NestedPropertyVisibilityBehavior), new PropertyMetadata(null, OnPropertyGridFieldChanged));
 
    public static readonly DependencyProperty ShouldDisplayNestedPropertiesProperty =
        DependencyProperty.Register("ShouldDisplayNestedProperties", typeof (bool),
            typeof (NestedPropertyVisibilityBehavior), new PropertyMetadata(false, OnShouldDisplayNestedPropertiesChanged));
 
    private bool _preventNesting;
 
    public PropertyGridField PropertyGridField
    {
        get { return (PropertyGridField)GetValue(PropertyGridFieldProperty); }
        set { SetValue(PropertyGridFieldProperty, value); }
    }
 
    public bool ShouldDisplayNestedProperties
    {
        get { return (bool)GetValue(ShouldDisplayNestedPropertiesProperty); }
        set { SetValue(ShouldDisplayNestedPropertiesProperty, value); }
    }
 
    private static void OnShouldDisplayNestedPropertiesChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var sender = (NestedPropertyVisibilityBehavior) d;
        sender.UpdateVisibility();
    }
 
    private static void OnPropertyGridFieldChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var field = e.NewValue as PropertyGridField;
 
        if (field == null)
            return;
 
        var propDef = field.DataContext as PropertyDefinition;
 
        if (propDef == null)
            return;
 
        var attrs = GetCustomAttributes(propDef.Instance, propDef.SourceProperty.Name);
        var sender = (NestedPropertyVisibilityBehavior) d;
 
        sender._preventNesting =  attrs.Any(x => x is PreventNestingAttribute);
        sender.UpdateVisibility();
    }
 
    protected override void OnAttached()
    {
        UpdateVisibility();
    }
 
    private void UpdateVisibility()
    {
        if (AssociatedObject == null)
            return;
 
        AssociatedObject.Visibility = ShouldDisplayNestedProperties && !_preventNesting
            ? Visibility.Visible
            : Visibility.Collapsed;
    }
 
    protected static object[] GetCustomAttributes(object source, string propertyPath)
    {
        if (source == null || string.IsNullOrEmpty(propertyPath))
            return null;
 
        PropertyInfo propertyInfo = null;
 
        var currentType = source.GetType();
        var path = propertyPath.Split('.');
 
        for (int i = 0, count = path.Length; i < count; i++)
        {
            var propertyStep = path[i];
            propertyInfo = currentType.GetProperty(propertyStep);
 
            if (propertyInfo == null || source == null || i == count - 1)
                break;
 
            source = propertyInfo.GetValue(source, null);
            currentType = propertyInfo.PropertyType;
        }
 
        return propertyInfo != null ? propertyInfo.GetCustomAttributes(true) : null;
    }
}

 

Attribute:

[AttributeUsage(AttributeTargets.Property)]
public sealed class PreventNestingAttribute : Attribute { }

 

Usage in your Settings item:

[PreventNesting]
//[Display(Name = "Margin")]
public Thickness Margin
{
    get
    {
        return _margin;
    }
 
    set { Set(() => Margin, ref _margin, value); }
}

 

I would be happy if it can be made more compact. I made it in haste.

 

Microsoft Silverlight (64-bit) Version: 5.1.41105.0
Windows 8.1 (64-bit)
Internet Explorer 11.0.9600.17416
Telerik 2017.1.117.1050

No answers yet. Maybe you can help?

Tags
PropertyGrid
Asked by
Art
Top achievements
Rank 1
Share this question
or