Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PropertyGrid: Hide search bar #817

Closed
wants to merge 9 commits into from
34 changes: 21 additions & 13 deletions src/Net_40/HandyControl_Net_40/Themes/Theme.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -9714,18 +9714,26 @@
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<DockPanel LastChildFill="True" Margin="0,0,0,6">
<hc:ButtonGroup Margin="0,0,6,0" Visibility="{Binding ShowSortButton,RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource Boolean2VisibilityConverter}}" Style="{StaticResource ButtonGroupSolid}">
<RadioButton Command="interactivity:ControlCommands.SortByCategory" IsChecked="True">
<Rectangle Width="16" Height="16" Fill="{StaticResource SortByCategoryDrawingBrush}" />
</RadioButton>
<RadioButton Command="interactivity:ControlCommands.SortByName">
<Rectangle Width="16" Height="16" Fill="{StaticResource SortByNameDrawingBrush}" />
</RadioButton>
</hc:ButtonGroup>
<hc:SearchBar x:Name="PART_SearchBar" IsRealTime="True" ShowClearButton="True" Style="{StaticResource SearchBarPlus}" />
</DockPanel>
<hc:PropertyItemsControl Grid.Row="1" x:Name="PART_ItemsControl" Style="{StaticResource PropertyItemsControlBaseStyle}">
<DockPanel LastChildFill="True" Margin="0,0,0,6">
<DockPanel.Visibility>
<MultiBinding Converter="{StaticResource BooleanArr2VisibilityConverter}"
ConverterParameter="UseAny">
<Binding Path="ShowSortButton" RelativeSource="{RelativeSource TemplatedParent}" />
<Binding Path="ShowSearchBar" RelativeSource="{RelativeSource TemplatedParent}" />
</MultiBinding>
</DockPanel.Visibility>
<hc:ButtonGroup Margin="0,0,6,0" Visibility="{Binding ShowSortButton,RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource Boolean2VisibilityConverter}}" Style="{StaticResource ButtonGroupSolid}">
<RadioButton Command="interactivity:ControlCommands.SortByCategory" IsChecked="True">
<Rectangle Width="16" Height="16" Fill="{StaticResource SortByCategoryDrawingBrush}" />
</RadioButton>
<RadioButton Command="interactivity:ControlCommands.SortByName">
<Rectangle Width="16" Height="16" Fill="{StaticResource SortByNameDrawingBrush}" />
</RadioButton>
</hc:ButtonGroup>
<hc:SearchBar x:Name="PART_SearchBar" IsRealTime="True" ShowClearButton="True" Style="{StaticResource SearchBarPlus}"
Visibility="{Binding ShowSearchBar, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource Boolean2VisibilityConverter}}" />
</DockPanel>
<hc:PropertyItemsControl Grid.Row="1" x:Name="PART_ItemsControl" Style="{StaticResource PropertyItemsControlBaseStyle}">
<hc:PropertyItemsControl.GroupStyle>
<GroupStyle ContainerStyle="{StaticResource PropertyGroupItemBaseStyle}" />
</hc:PropertyItemsControl.GroupStyle>
Expand Down Expand Up @@ -13294,4 +13302,4 @@
</Style>
<Style BasedOn="{StaticResource RangeSliderBaseStyle}" TargetType="hc:RangeSlider" />
<Style BasedOn="{StaticResource SliderBaseStyle}" TargetType="Slider" />
</ResourceDictionary>
</ResourceDictionary>
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ public class PropertyGridDemoModel
[Category("Category1")]
public Gender Enum { get; set; }

[Category("Category2")]
public DemoDataModel FlattenedType { get; set; }

public HorizontalAlignment HorizontalAlignment { get; set; }

public VerticalAlignment VerticalAlignment { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<hc:PropertyGrid Width="500" SelectedObject="{Binding DemoModel}"/>
<hc:PropertyGrid Width="500" SelectedObject="{Binding DemoModel}" FlattenChildProperties="ParentNameAsCategory"/>
<StackPanel hc:TitleElement.TitleWidth="168" Grid.Row="1" Margin="20,16,17,10">
<TextBox hc:TitleElement.Title="String" hc:TitleElement.TitlePlacement="Left" Style="{StaticResource TextBoxExtend}" Text="{Binding DemoModel.String,Mode=OneWay}" IsReadOnly="True"/>
<TextBox hc:TitleElement.Title="Enum" hc:TitleElement.TitlePlacement="Left" Style="{StaticResource TextBoxExtend}" Text="{Binding DemoModel.Enum,Mode=OneWay}" IsReadOnly="True" Margin="0,6,0,0"/>
Expand Down
109 changes: 93 additions & 16 deletions src/Shared/HandyControl_Shared/Controls/PropertyGrid/PropertyGrid.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using HandyControl.Data;
using HandyControl.Data.Enum;
using HandyControl.Interactivity;
using HandyControl.Tools.Extension;

Expand Down Expand Up @@ -102,6 +104,23 @@ public bool ShowSortButton
set => SetValue(ShowSortButtonProperty, value);
}

public static readonly DependencyProperty ShowSearchBarProperty = DependencyProperty.Register(
"ShowSearchBar", typeof(bool), typeof(PropertyGrid), new PropertyMetadata(ValueBoxes.TrueBox));

public bool ShowSearchBar
{
get => (bool) GetValue(ShowSearchBarProperty);
set => SetValue(ShowSearchBarProperty, value);

public static readonly DependencyProperty FlattenChildPropertiesProperty = DependencyProperty.Register(
"FlattenChildProperties", typeof(Flattening), typeof(PropertyGrid), new PropertyMetadata(Flattening.Off));

public Flattening FlattenChildProperties
{
get => (Flattening) GetValue(FlattenChildPropertiesProperty);
set => SetValue(FlattenChildPropertiesProperty, value);
}

public override void OnApplyTemplate()
{
if (_searchBar != null)
Expand All @@ -122,15 +141,72 @@ public override void OnApplyTemplate()
UpdateItems(SelectedObject);
}

/// <summary>
/// Algorithmic helper class to temporarily link parent data to a PropertyDescriptorCollection
/// </summary>
private class ParentPropertyDescriptorCollection
{
public ParentPropertyDescriptorCollection(PropertyDescriptorCollection properties, string category)
{
Properties = properties;
Category = category;
}

public PropertyDescriptorCollection Properties { get; }
public string Category { get; }
}

private IEnumerable<PropertyItem> FlattenUnknownProperties(PropertyDescriptorCollection propertiesToFlatten, string parentCategory)
{
var browsableProperties = propertiesToFlatten.OfType<PropertyDescriptor>()
.Where(item => PropertyResolver.ResolveIsBrowsable(item)).ToList();

var knownProperties = browsableProperties.Where(item => PropertyResolver.IsKnownEditorType(item.PropertyType))
.Select(item => CreatePropertyItem(item, parentCategory))
.Do(item => item.InitElement());

var unknownPropertiesCollections = browsableProperties.Where(item => !PropertyResolver.IsKnownEditorType(item.PropertyType))
.Select(GetCategorizedChildProperties);

return unknownPropertiesCollections
.Select(coll => FlattenUnknownProperties(coll.Properties, coll.Category))
.Aggregate(knownProperties, (current, flattenedChildProperties) => current.Concat(flattenedChildProperties));
}

private ParentPropertyDescriptorCollection GetCategorizedChildProperties(PropertyDescriptor parentItem)
{
string category = null;
switch (FlattenChildProperties)
{
case Flattening.ParentCategory:
category = PropertyResolver.ResolveCategory(parentItem);
break;
case Flattening.ParentNameAsCategory:
category = parentItem.DisplayName;
break;
}
return new ParentPropertyDescriptorCollection(parentItem.GetChildProperties(), category);
}

private void UpdateItems(object obj)
{
if (obj == null || _itemsControl == null) return;

_dataView = CollectionViewSource.GetDefaultView(TypeDescriptor.GetProperties(obj.GetType()).OfType<PropertyDescriptor>()
.Where(item => PropertyResolver.ResolveIsBrowsable(item)).Select(CreatePropertyItem)
.Do(item => item.InitElement()));
if (FlattenChildProperties == Flattening.Off)
{
_dataView = CollectionViewSource.GetDefaultView(TypeDescriptor.GetProperties(obj.GetType())
.OfType<PropertyDescriptor>()
.Where(item => PropertyResolver.ResolveIsBrowsable(item))
.Select(item => CreatePropertyItem(item, null))
.Do(item => item.InitElement()));
}
else
{
_dataView = CollectionViewSource.GetDefaultView(FlattenUnknownProperties(TypeDescriptor.GetProperties(obj.GetType()), null));
}

SortByCategory(null, null);

_itemsControl.ItemsSource = _dataView;
}

Expand Down Expand Up @@ -181,19 +257,20 @@ private void SearchBar_SearchStarted(object sender, FunctionEventArgs<string> e)
}
}

protected virtual PropertyItem CreatePropertyItem(PropertyDescriptor propertyDescriptor) => new()
{
Category = PropertyResolver.ResolveCategory(propertyDescriptor),
DisplayName = PropertyResolver.ResolveDisplayName(propertyDescriptor),
Description = PropertyResolver.ResolveDescription(propertyDescriptor),
IsReadOnly = PropertyResolver.ResolveIsReadOnly(propertyDescriptor),
DefaultValue = PropertyResolver.ResolveDefaultValue(propertyDescriptor),
Editor = PropertyResolver.ResolveEditor(propertyDescriptor),
Value = SelectedObject,
PropertyName = propertyDescriptor.Name,
PropertyType = propertyDescriptor.PropertyType,
PropertyTypeName = $"{propertyDescriptor.PropertyType.Namespace}.{propertyDescriptor.PropertyType.Name}"
};
protected virtual PropertyItem CreatePropertyItem(PropertyDescriptor propertyDescriptor, string category) =>
new()
{
Category = category ?? PropertyResolver.ResolveCategory(propertyDescriptor),
DisplayName = PropertyResolver.ResolveDisplayName(propertyDescriptor),
Description = PropertyResolver.ResolveDescription(propertyDescriptor),
IsReadOnly = PropertyResolver.ResolveIsReadOnly(propertyDescriptor),
DefaultValue = PropertyResolver.ResolveDefaultValue(propertyDescriptor),
Editor = PropertyResolver.ResolveEditor(propertyDescriptor),
Value = SelectedObject,
PropertyName = propertyDescriptor.Name,
PropertyType = propertyDescriptor.PropertyType,
PropertyTypeName = $"{propertyDescriptor.PropertyType.Namespace}.{propertyDescriptor.PropertyType.Name}"
};

protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@ public virtual PropertyEditorBase CreateDefaultEditor(Type type) =>

public virtual PropertyEditorBase CreateEditor(Type type) => Activator.CreateInstance(type) as PropertyEditorBase ?? new ReadOnlyTextPropertyEditor();

public static bool IsKnownEditorType(Type type) => TypeCodeDic.ContainsKey(type) || type.IsSubclassOf(typeof(Enum));

private enum EditorTypeCode
{
PlainText,
Expand Down
14 changes: 14 additions & 0 deletions src/Shared/HandyControl_Shared/Data/Enum/Flattening.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// -----------------------------
// Copyright (c) XION GmbH
// -----------------------------

namespace HandyControl.Data.Enum
{
public enum Flattening : byte
{
Off,
Uncategorized,
ParentCategory,
ParentNameAsCategory
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
<Compile Include="$(MSBuildThisFileDirectory)Controls\Text\SimpleText.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Controls\Window\GlowWindow.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Collections\DateTimeRangeComparer.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Data\Enum\Flattening.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Data\Enum\VisualWrapping.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Data\Flex\FlexContentJustify.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Data\Flex\FlexContentAlignment.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,13 @@
<RowDefinition/>
</Grid.RowDefinitions>
<DockPanel LastChildFill="True" Margin="0,0,0,6">
<DockPanel.Visibility>
<MultiBinding Converter="{StaticResource BooleanArr2VisibilityConverter}"
ConverterParameter="UseAny">
<Binding Path="ShowSortButton" RelativeSource="{RelativeSource TemplatedParent}"/>
<Binding Path="ShowSearchBar" RelativeSource="{RelativeSource TemplatedParent}"/>
</MultiBinding>
</DockPanel.Visibility>
<hc:ButtonGroup Margin="0,0,6,0" Visibility="{Binding ShowSortButton,RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource Boolean2VisibilityConverter}}" Style="{StaticResource ButtonGroupSolid}">
<RadioButton Command="interactivity:ControlCommands.SortByCategory" IsChecked="True">
<Rectangle Width="16" Height="16" Fill="{StaticResource SortByCategoryDrawingBrush}"/>
Expand All @@ -148,7 +155,8 @@
<Rectangle Width="16" Height="16" Fill="{StaticResource SortByNameDrawingBrush}"/>
</RadioButton>
</hc:ButtonGroup>
<hc:SearchBar x:Name="PART_SearchBar" IsRealTime="True" ShowClearButton="True" Style="{StaticResource SearchBarPlus}"/>
<hc:SearchBar x:Name="PART_SearchBar" IsRealTime="True" ShowClearButton="True" Style="{StaticResource SearchBarPlus}"
Visibility="{Binding ShowSearchBar,RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource Boolean2VisibilityConverter}}"/>
</DockPanel>
<hc:PropertyItemsControl Grid.Row="1" x:Name="PART_ItemsControl" Style="{StaticResource PropertyItemsControlBaseStyle}">
<hc:PropertyItemsControl.GroupStyle>
Expand Down
8 changes: 7 additions & 1 deletion src/Shared/HandyControl_Shared/Themes/Theme.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -9833,6 +9833,12 @@
<RowDefinition />
</Grid.RowDefinitions>
<DockPanel LastChildFill="True" Margin="0,0,0,6">
<DockPanel.Visibility>
<MultiBinding Converter="{StaticResource BooleanArr2VisibilityConverter}" ConverterParameter="UseAny">
<Binding Path="ShowSortButton" RelativeSource="{RelativeSource TemplatedParent}" />
<Binding Path="ShowSearchBar" RelativeSource="{RelativeSource TemplatedParent}" />
</MultiBinding>
</DockPanel.Visibility>
<hc:ButtonGroup Margin="0,0,6,0" Visibility="{Binding ShowSortButton,RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource Boolean2VisibilityConverter}}" Style="{StaticResource ButtonGroupSolid}">
<RadioButton Command="interactivity:ControlCommands.SortByCategory" IsChecked="True">
<Rectangle Width="16" Height="16" Fill="{StaticResource SortByCategoryDrawingBrush}" />
Expand All @@ -9841,7 +9847,7 @@
<Rectangle Width="16" Height="16" Fill="{StaticResource SortByNameDrawingBrush}" />
</RadioButton>
</hc:ButtonGroup>
<hc:SearchBar x:Name="PART_SearchBar" IsRealTime="True" ShowClearButton="True" Style="{StaticResource SearchBarPlus}" />
<hc:SearchBar x:Name="PART_SearchBar" IsRealTime="True" ShowClearButton="True" Style="{StaticResource SearchBarPlus}" Visibility="{Binding ShowSearchBar,RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource Boolean2VisibilityConverter}}" />
</DockPanel>
<hc:PropertyItemsControl Grid.Row="1" x:Name="PART_ItemsControl" Style="{StaticResource PropertyItemsControlBaseStyle}">
<hc:PropertyItemsControl.GroupStyle>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ public object Convert(object[] values, Type targetType, object parameter, Cultur
return Visibility.Collapsed;
}
}
if (parameter is string useAny && useAny == "UseAny")
{
return arr.Any(item => item) ? Visibility.Visible : Visibility.Collapsed;
}
return arr.All(item => item) ? Visibility.Visible : Visibility.Collapsed;
}

Expand Down