Auto hide empty category

Grids for WPF Forum

Posted 1 year ago by BenjaminLopVic - France
Version: 23.1.4
Avatar

Hello,

I followed the "Dynamic Properties" sample from the WPF Controls Sample Browser to help me hide some properties, and it works well.

However, if I hide all properties of a category, the category is still visible. How can I automatically hide it? Additionally, is it possible to hide an entire category instead of hiding each property individually?

Any insights or suggestions would be greatly appreciated.

Thank you in advance!

Benjamin.

Comments (8)

Answer - Posted 1 year ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hi Benjamin,

In that sample, we added an IsVisible property to the CustomPropertyModel class that inherits our PropertyDescriptorPropertyModel class.  You would probably need to do the same kind of thing by making a CustomCategoryModel and have it inherit our CategoryModel.  You could override the factory.CreateCategoryModel method to create your instance instead.  In the MainControl.xaml, you'd have to set the CategoryStyle property to a similar Style as the one for PropertyStyle. 

Perhaps when your CustomPropertyModel's IsVisible value changes, you could look at its Parent and if it's a CustomCategoryModel, call its InvalidateIsVisible method too.  Then the CustomCategoryModel.IsVisible property would need to look at its contained properties and see if any were visible for it to be true.

That is probably the general approach we'd take to get categories hiding as well.


Actipro Software Support

Posted 1 year ago by BenjaminLopVic - France
Avatar

Hello,

Thank you very much, this solution is perfect.

Benjamin.

[Modified 1 year ago]

Posted 4 months ago by BenjaminLopVic - France
Avatar

Hello,

This worked fine until I introduced nested categories. The solution isn’t complicated, but it took me a while to figure out, so I’m sharing it here in case it helps anyone.

As I mentioned, when the IsVisible value of my CustomPropertyModel changes, it calls InvalidateIsVisible if its Parent is a CustomCategoryModel. For a nested category, it’s just as simple: if its Parent is also a CustomCategoryModel, it calls InvalidateIsVisible as well!

Benjamin

Posted 4 months ago by Nishant
Avatar
Posted 4 months ago by BenjaminLopVic - France
Avatar

Hello,

If its not too late, here is a sample for an auto-hidding category that becomes hidden when all its children are hidden:

interface IHideableElement
{
    bool IsVisible { get; }
}
class CustomPropertyModel : PropertyDescriptorPropertyModel, IHideableElement
{
    private bool? isVisible;

    private void InvalidateIsVisible()
    {
        isVisible = null;
        this.NotifyPropertyChanged(nameof(IsVisible));
        if (this.Parent is AutoHiddingCategoryModel customCategoryModel)
        {
            customCategoryModel.InvalidateIsVisible();
        }
    }

    public bool IsVisible
    {
        get
        {
            if (!isVisible.HasValue)
            {
                //Get whether the propertyModel should be visible or not
            }

            return isVisible.Value;
        }
    }
}
class AutoHiddingCategoryModel : CategoryModel, IHideableElement
{
    private bool? isVisible;

    internal void InvalidateIsVisible()
    {
        isVisible = null;
        this.NotifyPropertyChanged(nameof(IsVisible));
        if (this.Parent is AutoHiddingCategoryModel customCategoryModel)
        {
            customCategoryModel.InvalidateIsVisible();
        }
    }

    public bool IsVisible
    {
        get
        {
            if (!isVisible.HasValue)
            {
                isVisible = Children.Any(model => model is IHideableElement iVisibility && iVisibility.IsVisible);
            }

            return isVisible.Value;
        }
    }
}

And you can invalidate the visibility of a property when the value changes, for example :

protected override void OnPropertyChanged(PropertyChangedEventArgs e)
{
    base.OnPropertyChanged(e);

    if (e.PropertyName == nameof(ValueAsString))
    {
        InvalidateIsVisible();
    }
}

[Modified 4 months ago]

Posted 4 months ago by Nishant
Avatar

Thanks for the code snippet. Just one question.
In the MainControl.xaml, Are you setting style for both CategoryStyle and PropertyStyle. Can you share the code for the xaml too.

[Modified 4 months ago]

Posted 4 months ago by BenjaminLopVic - France
Avatar

Yes, I forget that :

 <Style x:Key="CategoryPropertyGridItemStyle" TargetType="grids:PropertyGridItem" >
     <Setter Property="Background" Value="{DynamicResource {x:Static themes:AssetResourceKeys.ListGridLineBackgroundNormalBrushKey}}" />
     <Setter Property="BorderThickness" Value="0" />
     <Setter Property="FontWeight" Value="Bold" />
     <Setter Property="Padding" Value="5,3" />

     <Setter Property="Template">
         <Setter.Value>
             <ControlTemplate TargetType="grids:PropertyGridItem">
                 <Border x:Name="gridLineBorder" BorderBrush="{TemplateBinding GridLineBrush}" BorderThickness="0,0,0,1" SnapsToDevicePixels="True">
                     <Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
                         <gridsPrimitives:PropertyGridItemContentPanel>
                             <gridsPrimitives:TreeItemExpansionToggleButton x:Name="PART_ExpanderButton" Style="{TemplateBinding ToggleExpansionButtonStyle}" 
								Visibility="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IsExpandable, Converter={StaticResource BooleanToVisibilityConverter}}" 
								IsChecked="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IsExpanded, Mode=TwoWay}" />

                             <shared:PixelSnapper VerticalRoundMode="CeilingToEven">
                                 <Grid HorizontalAlignment="Left">
                                     <Rectangle x:Name="focusVisual" Margin="0,1" StrokeThickness="1" 
											   Stroke="{DynamicResource {x:Static themes:AssetResourceKeys.ContainerForegroundLowDisabledBrushKey}}" StrokeDashArray="1 2" 
											   SnapsToDevicePixels="True" Visibility="Collapsed" />

                                     <TextBlock Margin="{TemplateBinding Padding}" Text="{Binding DisplayName}" TextTrimming="CharacterEllipsis" VerticalAlignment="Center" />
                                 </Grid>
                             </shared:PixelSnapper>
                         </gridsPrimitives:PropertyGridItemContentPanel>
                     </Border>
                 </Border>

                 <ControlTemplate.Triggers>
                     <Trigger Property="GridLineBrush" Value="{x:Null}">
                         <Setter TargetName="gridLineBorder" Property="BorderThickness" Value="0" />
                     </Trigger>
                     <MultiTrigger>
                         <MultiTrigger.Conditions>
                             <Condition Property="IsSelected" Value="true" />
                             <Condition Property="grids:TreeListBox.IsSelectionActive" Value="true" />
                         </MultiTrigger.Conditions>
                         <Setter TargetName="focusVisual" Property="Visibility" Value="Visible" />
                     </MultiTrigger>
                 </ControlTemplate.Triggers>
             </ControlTemplate>
         </Setter.Value>
     </Setter>
 </Style>

And in my PropertyGrid :

<grids:PropertyGrid.ItemContainerStyleSelector>
    <grids:PropertyGridItemStyleSelector>
        <grids:PropertyGridItemStyleSelector.PropertyStyle>
            <Style TargetType="grids:PropertyGridItem">
                <Setter Property="Visibility" Value="{Binding IsVisible, Converter={StaticResource BooleanToVisibilityConverter}}" />
            </Style>
        </grids:PropertyGridItemStyleSelector.PropertyStyle>
        <grids:PropertyGridItemStyleSelector.CategoryStyle>
            <Style TargetType="grids:PropertyGridItem" BasedOn="{StaticResource CategoryPropertyGridItemStyle}">
                <Setter Property="Visibility" Value="{Binding IsVisible, Converter={StaticResource BooleanToVisibilityConverter}}" />
            </Style>
        </grids:PropertyGridItemStyleSelector.CategoryStyle>
    </grids:PropertyGridItemStyleSelector>
</grids:PropertyGrid.ItemContainerStyleSelector>

[Modified 4 months ago]

Posted 4 months ago by Nishant
Avatar

Thanks for the quick response. It was quite helpful.

The latest build of this product (v24.1.4) was released 3 months ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.