From 1edd0723d0c5ed33bf8b494a403403ec29787112 Mon Sep 17 00:00:00 2001 From: John Date: Sun, 29 Mar 2026 10:57:26 +0800 Subject: [PATCH 1/5] =?UTF-8?q?=E6=B7=BB=E5=8A=A0PropetyGrid.CategoryOrder?= =?UTF-8?q?=EF=BC=8C=E7=94=A8=E4=BA=8E=E5=88=86=E7=B1=BB=E7=9A=84=E8=87=AA?= =?UTF-8?q?=E5=AE=9A=E4=B9=89=E6=8E=92=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controls/PropertyGridDemo.xaml | 12 ++++- .../Controls/PropertyGrid/PropertyGrid.cs | 54 ++++++++++++++++++- .../Controls/PropertyGrid/PropertyItem.cs | 11 +++- 3 files changed, 73 insertions(+), 4 deletions(-) diff --git a/src/Shared/HandyControlDemo_Shared/UserControl/Controls/PropertyGridDemo.xaml b/src/Shared/HandyControlDemo_Shared/UserControl/Controls/PropertyGridDemo.xaml index 8736f48e2..b5553c660 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,14 @@ - + + + + Category2 + Category1 + + + diff --git a/src/Shared/HandyControl_Shared/Controls/PropertyGrid/PropertyGrid.cs b/src/Shared/HandyControl_Shared/Controls/PropertyGrid/PropertyGrid.cs index 1f6365ce2..24a9ebf6c 100644 --- a/src/Shared/HandyControl_Shared/Controls/PropertyGrid/PropertyGrid.cs +++ b/src/Shared/HandyControl_Shared/Controls/PropertyGrid/PropertyGrid.cs @@ -1,5 +1,7 @@ -using System; +using System; +using System; using System.ComponentModel; +using System.Collections.Generic; using System.Linq; using System.Windows; using System.Windows.Controls; @@ -102,6 +104,34 @@ 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 override void OnApplyTemplate() { if (_searchBar != null) @@ -130,10 +160,31 @@ private void UpdateItems(object obj) .Where(item => PropertyResolver.ResolveIsBrowsable(item)).Select(CreatePropertyItem) .Do(item => item.InitElement())); + UpdateCategoryOrder(); + 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 SortByCategory(object sender, ExecutedRoutedEventArgs e) { if (_dataView == null) return; @@ -142,6 +193,7 @@ 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.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..209b5afe4 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,15 @@ 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 EditorProperty = DependencyProperty.Register( nameof(Editor), typeof(PropertyEditorBase), typeof(PropertyItem), new PropertyMetadata(default(PropertyEditorBase))); From aa3c61c71c101d1d6820f105dd597ffc0d2b2824 Mon Sep 17 00:00:00 2001 From: John Date: Sun, 29 Mar 2026 11:15:49 +0800 Subject: [PATCH 2/5] =?UTF-8?q?=E6=B7=BB=E5=8A=A0PropetyGrid.PropertyOrder?= =?UTF-8?q?=EF=BC=8C=E7=94=A8=E4=BA=8E=E5=B1=9E=E6=80=A7=E7=9A=84=E8=87=AA?= =?UTF-8?q?=E5=AE=9A=E4=B9=89=E6=8E=92=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Data/Model/PropertyGridDemoModel.cs | 4 +- .../Controls/PropertyGridDemo.xaml | 9 ++++ .../Controls/PropertyGrid/PropertyGrid.cs | 49 +++++++++++++++++++ .../Controls/PropertyGrid/PropertyItem.cs | 9 ++++ 4 files changed, 69 insertions(+), 2 deletions(-) diff --git a/src/Shared/HandyControlDemo_Shared/Data/Model/PropertyGridDemoModel.cs b/src/Shared/HandyControlDemo_Shared/Data/Model/PropertyGridDemoModel.cs index 073453e1d..68e14c843 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; } diff --git a/src/Shared/HandyControlDemo_Shared/UserControl/Controls/PropertyGridDemo.xaml b/src/Shared/HandyControlDemo_Shared/UserControl/Controls/PropertyGridDemo.xaml index b5553c660..389aaaf1d 100644 --- a/src/Shared/HandyControlDemo_Shared/UserControl/Controls/PropertyGridDemo.xaml +++ b/src/Shared/HandyControlDemo_Shared/UserControl/Controls/PropertyGridDemo.xaml @@ -18,6 +18,15 @@ Category1 + + + Boolean + Integer + Enum + String + ImageSource + + diff --git a/src/Shared/HandyControl_Shared/Controls/PropertyGrid/PropertyGrid.cs b/src/Shared/HandyControl_Shared/Controls/PropertyGrid/PropertyGrid.cs index 24a9ebf6c..9d283b1b5 100644 --- a/src/Shared/HandyControl_Shared/Controls/PropertyGrid/PropertyGrid.cs +++ b/src/Shared/HandyControl_Shared/Controls/PropertyGrid/PropertyGrid.cs @@ -132,6 +132,34 @@ public IEnumerable CategoryOrder 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) @@ -161,6 +189,7 @@ private void UpdateItems(object obj) .Do(item => item.InitElement())); UpdateCategoryOrder(); + UpdatePropertyOrder(); SortByCategory(null, null); _itemsControl.ItemsSource = _dataView; @@ -185,6 +214,25 @@ private void UpdateCategoryOrder() } } + 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; @@ -195,6 +243,7 @@ private void SortByCategory(object sender, ExecutedRoutedEventArgs e) _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 209b5afe4..a9725e763 100644 --- a/src/Shared/HandyControl_Shared/Controls/PropertyGrid/PropertyItem.cs +++ b/src/Shared/HandyControl_Shared/Controls/PropertyGrid/PropertyItem.cs @@ -98,6 +98,15 @@ public int CategoryOrder 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))); From 9e327f49b981347552417e765f8723122820a3f2 Mon Sep 17 00:00:00 2001 From: John Date: Tue, 31 Mar 2026 12:27:25 +0800 Subject: [PATCH 3/5] =?UTF-8?q?=E6=B7=BB=E5=8A=A0EnumPropertyEditor?= =?UTF-8?q?=E5=AF=B9=E6=9E=9A=E4=B8=BE=E5=85=83=E7=B4=A0Description?= =?UTF-8?q?=E7=9A=84=E6=98=BE=E7=A4=BA=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Data/Model/PropertyGridDemoModel.cs | 2 ++ .../Editors/EnumPropertyEditor.cs | 27 +++++++++++++++++-- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/Shared/HandyControlDemo_Shared/Data/Model/PropertyGridDemoModel.cs b/src/Shared/HandyControlDemo_Shared/Data/Model/PropertyGridDemoModel.cs index 68e14c843..c9ac88153 100644 --- a/src/Shared/HandyControlDemo_Shared/Data/Model/PropertyGridDemoModel.cs +++ b/src/Shared/HandyControlDemo_Shared/Data/Model/PropertyGridDemoModel.cs @@ -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/HandyControl_Shared/Controls/PropertyGrid/Editors/EnumPropertyEditor.cs b/src/Shared/HandyControl_Shared/Controls/PropertyGrid/Editors/EnumPropertyEditor.cs index 070b634b2..2ce2fee83 100644 --- a/src/Shared/HandyControl_Shared/Controls/PropertyGrid/Editors/EnumPropertyEditor.cs +++ b/src/Shared/HandyControl_Shared/Controls/PropertyGrid/Editors/EnumPropertyEditor.cs @@ -1,6 +1,10 @@ -using System; +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 +13,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 + }; + } + } } From 1c8d5839ff96472543226a2fd4ee3994c2bc84d9 Mon Sep 17 00:00:00 2001 From: John Date: Tue, 31 Mar 2026 18:15:44 +0800 Subject: [PATCH 4/5] Update src/Shared/HandyControl_Shared/Controls/PropertyGrid/PropertyGrid.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../HandyControl_Shared/Controls/PropertyGrid/PropertyGrid.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Shared/HandyControl_Shared/Controls/PropertyGrid/PropertyGrid.cs b/src/Shared/HandyControl_Shared/Controls/PropertyGrid/PropertyGrid.cs index 9d283b1b5..6f05719ae 100644 --- a/src/Shared/HandyControl_Shared/Controls/PropertyGrid/PropertyGrid.cs +++ b/src/Shared/HandyControl_Shared/Controls/PropertyGrid/PropertyGrid.cs @@ -1,5 +1,4 @@ using System; -using System; using System.ComponentModel; using System.Collections.Generic; using System.Linq; From 1ea84e2b8234ffeaef951ab88384b12373b2ad11 Mon Sep 17 00:00:00 2001 From: John Date: Tue, 31 Mar 2026 18:16:47 +0800 Subject: [PATCH 5/5] Update src/Shared/HandyControl_Shared/Controls/PropertyGrid/Editors/EnumPropertyEditor.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../Controls/PropertyGrid/Editors/EnumPropertyEditor.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Shared/HandyControl_Shared/Controls/PropertyGrid/Editors/EnumPropertyEditor.cs b/src/Shared/HandyControl_Shared/Controls/PropertyGrid/Editors/EnumPropertyEditor.cs index 2ce2fee83..c668d0297 100644 --- a/src/Shared/HandyControl_Shared/Controls/PropertyGrid/Editors/EnumPropertyEditor.cs +++ b/src/Shared/HandyControl_Shared/Controls/PropertyGrid/Editors/EnumPropertyEditor.cs @@ -1,5 +1,4 @@ using System; -using System; using System.Collections.Generic; using System.ComponentModel; using System.Windows;