123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203 |
- using System;
- 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.Interactivity;
- using HandyControl.Tools.Extension;
- namespace HandyControl.Controls;
- [TemplatePart(Name = ElementItemsControl, Type = typeof(ItemsControl))]
- [TemplatePart(Name = ElementSearchBar, Type = typeof(SearchBar))]
- public class PropertyGrid : Control
- {
- private const string ElementItemsControl = "PART_ItemsControl";
- private const string ElementSearchBar = "PART_SearchBar";
- private ItemsControl _itemsControl;
- private ICollectionView _dataView;
- private SearchBar _searchBar;
- private string _searchKey;
- public PropertyGrid()
- {
- CommandBindings.Add(new CommandBinding(ControlCommands.SortByCategory, SortByCategory, (s, e) => e.CanExecute = ShowSortButton));
- CommandBindings.Add(new CommandBinding(ControlCommands.SortByName, SortByName, (s, e) => e.CanExecute = ShowSortButton));
- }
- public virtual PropertyResolver PropertyResolver { get; } = new();
- public static readonly RoutedEvent SelectedObjectChangedEvent =
- EventManager.RegisterRoutedEvent("SelectedObjectChanged", RoutingStrategy.Bubble,
- typeof(RoutedPropertyChangedEventHandler<object>), typeof(PropertyGrid));
- public event RoutedPropertyChangedEventHandler<object> SelectedObjectChanged
- {
- add => AddHandler(SelectedObjectChangedEvent, value);
- remove => RemoveHandler(SelectedObjectChangedEvent, value);
- }
- public static readonly DependencyProperty SelectedObjectProperty = DependencyProperty.Register(
- nameof(SelectedObject), typeof(object), typeof(PropertyGrid), new PropertyMetadata(default, OnSelectedObjectChanged));
- private static void OnSelectedObjectChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- var ctl = (PropertyGrid) d;
- ctl.OnSelectedObjectChanged(e.OldValue, e.NewValue);
- }
- public object SelectedObject
- {
- get => GetValue(SelectedObjectProperty);
- set => SetValue(SelectedObjectProperty, value);
- }
- protected virtual void OnSelectedObjectChanged(object oldValue, object newValue)
- {
- UpdateItems(newValue);
- RaiseEvent(new RoutedPropertyChangedEventArgs<object>(oldValue, newValue, SelectedObjectChangedEvent));
- }
- public static readonly DependencyProperty DescriptionProperty = DependencyProperty.Register(
- nameof(Description), typeof(string), typeof(PropertyGrid), new PropertyMetadata(default(string)));
- public string Description
- {
- get => (string) GetValue(DescriptionProperty);
- set => SetValue(DescriptionProperty, value);
- }
- public static readonly DependencyProperty MaxTitleWidthProperty = DependencyProperty.Register(
- nameof(MaxTitleWidth), typeof(double), typeof(PropertyGrid), new PropertyMetadata(ValueBoxes.Double0Box));
- public double MaxTitleWidth
- {
- get => (double) GetValue(MaxTitleWidthProperty);
- set => SetValue(MaxTitleWidthProperty, value);
- }
- public static readonly DependencyProperty MinTitleWidthProperty = DependencyProperty.Register(
- nameof(MinTitleWidth), typeof(double), typeof(PropertyGrid), new PropertyMetadata(ValueBoxes.Double0Box));
- public double MinTitleWidth
- {
- get => (double) GetValue(MinTitleWidthProperty);
- set => SetValue(MinTitleWidthProperty, value);
- }
- public static readonly DependencyProperty ShowSortButtonProperty = DependencyProperty.Register(
- nameof(ShowSortButton), typeof(bool), typeof(PropertyGrid), new PropertyMetadata(ValueBoxes.TrueBox));
- public bool ShowSortButton
- {
- get => (bool) GetValue(ShowSortButtonProperty);
- set => SetValue(ShowSortButtonProperty, ValueBoxes.BooleanBox(value));
- }
- public override void OnApplyTemplate()
- {
- if (_searchBar != null)
- {
- _searchBar.SearchStarted -= SearchBar_SearchStarted;
- }
- base.OnApplyTemplate();
- _itemsControl = GetTemplateChild(ElementItemsControl) as ItemsControl;
- _searchBar = GetTemplateChild(ElementSearchBar) as SearchBar;
- if (_searchBar != null)
- {
- _searchBar.SearchStarted += SearchBar_SearchStarted;
- }
- UpdateItems(SelectedObject);
- }
- 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()));
- SortByCategory(null, null);
- _itemsControl.ItemsSource = _dataView;
- }
- private void SortByCategory(object sender, ExecutedRoutedEventArgs e)
- {
- if (_dataView == null) return;
- using (_dataView.DeferRefresh())
- {
- _dataView.GroupDescriptions.Clear();
- _dataView.SortDescriptions.Clear();
- _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));
- }
- }
- private void SortByName(object sender, ExecutedRoutedEventArgs e)
- {
- if (_dataView == null) return;
- using (_dataView.DeferRefresh())
- {
- _dataView.GroupDescriptions.Clear();
- _dataView.SortDescriptions.Clear();
- _dataView.SortDescriptions.Add(new SortDescription(PropertyItem.PropertyNameProperty.Name, ListSortDirection.Ascending));
- }
- }
- private void SearchBar_SearchStarted(object sender, FunctionEventArgs<string> e)
- {
- if (_dataView == null) return;
- _searchKey = e.Info;
- if (string.IsNullOrEmpty(_searchKey))
- {
- foreach (UIElement item in _dataView)
- {
- item.Show();
- }
- }
- else
- {
- foreach (PropertyItem item in _dataView)
- {
- item.Show(item.PropertyName.ToLower().Contains(_searchKey) || item.DisplayName.ToLower().Contains(_searchKey));
- }
- }
- }
- 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 override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
- {
- base.OnRenderSizeChanged(sizeInfo);
- TitleElement.SetTitleWidth(this, new GridLength(Math.Max(MinTitleWidth, Math.Min(MaxTitleWidth, ActualWidth / 3))));
- }
- }
|