diff --git a/src/Shared/HandyControlDemo_Shared/Data/Model/PropertyGridDemoModel.cs b/src/Shared/HandyControlDemo_Shared/Data/Model/PropertyGridDemoModel.cs index 073453e1d..c9ac88153 100644 --- a/src/Shared/HandyControlDemo_Shared/Data/Model/PropertyGridDemoModel.cs +++ b/src/Shared/HandyControlDemo_Shared/Data/Model/PropertyGridDemoModel.cs @@ -1,4 +1,4 @@ -using System.ComponentModel; +using System.ComponentModel; using System.Windows; using System.Windows.Media; @@ -15,7 +15,7 @@ public class PropertyGridDemoModel [Category("Category2")] public bool Boolean { get; set; } - [Category("Category1")] + [Category("Category2")] public Gender Enum { get; set; } public HorizontalAlignment HorizontalAlignment { get; set; } @@ -27,6 +27,8 @@ public class PropertyGridDemoModel public enum Gender { + [Description("Boy/Man/Male")] Male, + [Description("Girl/Woman/Female")] Female } diff --git a/src/Shared/HandyControlDemo_Shared/UserControl/Controls/PropertyGridDemo.xaml b/src/Shared/HandyControlDemo_Shared/UserControl/Controls/PropertyGridDemo.xaml index 8736f48e2..389aaaf1d 100644 --- a/src/Shared/HandyControlDemo_Shared/UserControl/Controls/PropertyGridDemo.xaml +++ b/src/Shared/HandyControlDemo_Shared/UserControl/Controls/PropertyGridDemo.xaml @@ -1,6 +1,7 @@ - @@ -10,7 +11,23 @@ - + + + + Category2 + Category1 + + + + + Boolean + Integer + Enum + String + ImageSource + + + diff --git a/src/Shared/HandyControl_Shared/Controls/PropertyGrid/Editors/EnumPropertyEditor.cs b/src/Shared/HandyControl_Shared/Controls/PropertyGrid/Editors/EnumPropertyEditor.cs index 070b634b2..c668d0297 100644 --- a/src/Shared/HandyControl_Shared/Controls/PropertyGrid/Editors/EnumPropertyEditor.cs +++ b/src/Shared/HandyControl_Shared/Controls/PropertyGrid/Editors/EnumPropertyEditor.cs @@ -1,6 +1,9 @@ -using System; +using System; +using System.Collections.Generic; +using System.ComponentModel; using System.Windows; using System.Windows.Controls.Primitives; +using HandyControl.Data; namespace HandyControl.Controls; @@ -9,8 +12,27 @@ public class EnumPropertyEditor : PropertyEditorBase public override FrameworkElement CreateElement(PropertyItem propertyItem) => new System.Windows.Controls.ComboBox { IsEnabled = !propertyItem.IsReadOnly, - ItemsSource = Enum.GetValues(propertyItem.PropertyType) + ItemsSource = CreateEnumItems(propertyItem.PropertyType), + DisplayMemberPath = nameof(EnumItem.Description), + SelectedValuePath = nameof(EnumItem.Value) }; public override DependencyProperty GetDependencyProperty() => Selector.SelectedValueProperty; + + private static IEnumerable CreateEnumItems(Type enumType) + { + foreach (Enum value in Enum.GetValues(enumType)) + { + var fieldInfo = enumType.GetField(value.ToString()); + var description = fieldInfo?.GetCustomAttributes(typeof(DescriptionAttribute), true) is DescriptionAttribute[] { Length: > 0 } attributes + ? attributes[0].Description + : value.ToString(); + + yield return new EnumItem + { + Description = description, + Value = value + }; + } + } } diff --git a/src/Shared/HandyControl_Shared/Controls/PropertyGrid/PropertyGrid.cs b/src/Shared/HandyControl_Shared/Controls/PropertyGrid/PropertyGrid.cs index 1f6365ce2..6f05719ae 100644 --- a/src/Shared/HandyControl_Shared/Controls/PropertyGrid/PropertyGrid.cs +++ b/src/Shared/HandyControl_Shared/Controls/PropertyGrid/PropertyGrid.cs @@ -1,5 +1,6 @@ -using System; +using System; using System.ComponentModel; +using System.Collections.Generic; using System.Linq; using System.Windows; using System.Windows.Controls; @@ -102,6 +103,62 @@ public bool ShowSortButton set => SetValue(ShowSortButtonProperty, ValueBoxes.BooleanBox(value)); } + public static readonly DependencyProperty CategoryOrderProperty = DependencyProperty.Register( + nameof(CategoryOrder), typeof(IEnumerable), typeof(PropertyGrid), + new PropertyMetadata(default(IEnumerable), OnCategoryOrderChanged)); + + private static void OnCategoryOrderChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var ctl = (PropertyGrid) d; + ctl.OnCategoryOrderChanged(); + } + + protected virtual void OnCategoryOrderChanged() + { + if (_dataView == null) return; + + UpdateCategoryOrder(); + + if (_dataView.GroupDescriptions.OfType().Any(group => group.PropertyName == PropertyItem.CategoryProperty.Name)) + { + SortByCategory(null, null); + } + } + + public IEnumerable CategoryOrder + { + get => (IEnumerable) GetValue(CategoryOrderProperty); + set => SetValue(CategoryOrderProperty, value); + } + + public static readonly DependencyProperty PropertyOrderProperty = DependencyProperty.Register( + nameof(PropertyOrder), typeof(IEnumerable), typeof(PropertyGrid), + new PropertyMetadata(default(IEnumerable), OnPropertyOrderChanged)); + + private static void OnPropertyOrderChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var ctl = (PropertyGrid) d; + ctl.OnPropertyOrderChanged(); + } + + protected virtual void OnPropertyOrderChanged() + { + if (_dataView == null) return; + + UpdatePropertyOrder(); + + if (_dataView.GroupDescriptions.OfType().Any(group => group.PropertyName == PropertyItem.CategoryProperty.Name)) + { + SortByCategory(null, null); + } + } + + public IEnumerable PropertyOrder + { + get => (IEnumerable) GetValue(PropertyOrderProperty); + set => SetValue(PropertyOrderProperty, value); + } + public override void OnApplyTemplate() { if (_searchBar != null) @@ -130,10 +187,51 @@ private void UpdateItems(object obj) .Where(item => PropertyResolver.ResolveIsBrowsable(item)).Select(CreatePropertyItem) .Do(item => item.InitElement())); + UpdateCategoryOrder(); + UpdatePropertyOrder(); + SortByCategory(null, null); _itemsControl.ItemsSource = _dataView; } + private void UpdateCategoryOrder() + { + if (_dataView?.SourceCollection == null) return; + + var categoryOrderDic = new Dictionary(StringComparer.OrdinalIgnoreCase); + var index = 0; + + foreach (var category in CategoryOrder ?? Enumerable.Empty()) + { + if (string.IsNullOrWhiteSpace(category) || categoryOrderDic.ContainsKey(category)) continue; + categoryOrderDic[category] = index++; + } + + foreach (var item in _dataView.SourceCollection.OfType()) + { + item.CategoryOrder = categoryOrderDic.TryGetValue(item.Category, out var order) ? order : int.MaxValue; + } + } + + private void UpdatePropertyOrder() + { + if (_dataView?.SourceCollection == null) return; + + var propertyOrderDic = new Dictionary(StringComparer.OrdinalIgnoreCase); + var index = 0; + + foreach (var propertyName in PropertyOrder ?? Enumerable.Empty()) + { + if (string.IsNullOrWhiteSpace(propertyName) || propertyOrderDic.ContainsKey(propertyName)) continue; + propertyOrderDic[propertyName] = index++; + } + + foreach (var item in _dataView.SourceCollection.OfType()) + { + item.PropertyOrder = propertyOrderDic.TryGetValue(item.PropertyName, out var order) ? order : int.MaxValue; + } + } + private void SortByCategory(object sender, ExecutedRoutedEventArgs e) { if (_dataView == null) return; @@ -142,7 +240,9 @@ private void SortByCategory(object sender, ExecutedRoutedEventArgs e) { _dataView.GroupDescriptions.Clear(); _dataView.SortDescriptions.Clear(); + _dataView.SortDescriptions.Add(new SortDescription(PropertyItem.CategoryOrderProperty.Name, ListSortDirection.Ascending)); _dataView.SortDescriptions.Add(new SortDescription(PropertyItem.CategoryProperty.Name, ListSortDirection.Ascending)); + _dataView.SortDescriptions.Add(new SortDescription(PropertyItem.PropertyOrderProperty.Name, ListSortDirection.Ascending)); _dataView.SortDescriptions.Add(new SortDescription(PropertyItem.DisplayNameProperty.Name, ListSortDirection.Ascending)); _dataView.GroupDescriptions.Add(new PropertyGroupDescription(PropertyItem.CategoryProperty.Name)); } diff --git a/src/Shared/HandyControl_Shared/Controls/PropertyGrid/PropertyItem.cs b/src/Shared/HandyControl_Shared/Controls/PropertyGrid/PropertyItem.cs index 658e31c84..a9725e763 100644 --- a/src/Shared/HandyControl_Shared/Controls/PropertyGrid/PropertyItem.cs +++ b/src/Shared/HandyControl_Shared/Controls/PropertyGrid/PropertyItem.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.ComponentModel; using System.Windows; using System.Windows.Controls; @@ -89,6 +89,24 @@ public string Category set => SetValue(CategoryProperty, value); } + public static readonly DependencyProperty CategoryOrderProperty = DependencyProperty.Register( + nameof(CategoryOrder), typeof(int), typeof(PropertyItem), new PropertyMetadata(default(int))); + + public int CategoryOrder + { + get => (int) GetValue(CategoryOrderProperty); + set => SetValue(CategoryOrderProperty, value); + } + + public static readonly DependencyProperty PropertyOrderProperty = DependencyProperty.Register( + nameof(PropertyOrder), typeof(int), typeof(PropertyItem), new PropertyMetadata(default(int))); + + public int PropertyOrder + { + get => (int) GetValue(PropertyOrderProperty); + set => SetValue(PropertyOrderProperty, value); + } + public static readonly DependencyProperty EditorProperty = DependencyProperty.Register( nameof(Editor), typeof(PropertyEditorBase), typeof(PropertyItem), new PropertyMetadata(default(PropertyEditorBase)));