add PropertyGrid Demo
This commit is contained in:
1 parent
0a9d95fafd
commit
f7a39f3d32
18 files changed
+320
-82
No files matched your search
@@ -0,0 +1,19 @@
|
||||
using System.Windows;
|
||||
|
||||
namespace HandyControl.Controls
|
||||
{
|
||||
public class DatePropertyEditor : PropertyEditorBase
|
||||
{
|
||||
public override FrameworkElement CreateElement(PropertyItem propertyItem)
|
||||
{
|
||||
var picker = new DateTimePicker
|
||||
{
|
||||
IsEnabled = !propertyItem.IsReadOnly
|
||||
};
|
||||
|
||||
picker.SetBinding(System.Windows.Controls.DatePicker.SelectedDateProperty, CreateBinding(propertyItem));
|
||||
|
||||
return picker;
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -2,9 +2,9 @@
|
||||
|
||||
namespace HandyControl.Controls
|
||||
{
|
||||
public class IntegerPropertyEditor : PropertyEditorBase
|
||||
public class NumberPropertyEditor : PropertyEditorBase
|
||||
{
|
||||
public IntegerPropertyEditor(double minimum, double maximum)
|
||||
public NumberPropertyEditor(double minimum, double maximum)
|
||||
{
|
||||
Minimum = minimum;
|
||||
Maximum = maximum;
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
using System.Windows;
|
||||
|
||||
namespace HandyControl.Controls
|
||||
{
|
||||
public class NumberPropertyEditor : PropertyEditorBase
|
||||
{
|
||||
public NumberPropertyEditor()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public NumberPropertyEditor(double minimum, double maximum)
|
||||
{
|
||||
Minimum = minimum;
|
||||
Maximum = maximum;
|
||||
}
|
||||
|
||||
public double Minimum { get; set; }
|
||||
|
||||
public double Maximum { get; set; }
|
||||
|
||||
public override FrameworkElement CreateElement(PropertyItem propertyItem)
|
||||
{
|
||||
var numericUpDown = new NumericUpDown
|
||||
{
|
||||
IsReadOnly = propertyItem.IsReadOnly,
|
||||
Minimum = Minimum,
|
||||
Maximum = Maximum
|
||||
};
|
||||
|
||||
numericUpDown.SetBinding(NumericUpDown.ValueProperty, CreateBinding(propertyItem));
|
||||
|
||||
return numericUpDown;
|
||||
}
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
using System.Windows;
|
||||
|
||||
namespace HandyControl.Controls
|
||||
{
|
||||
public class PlainTextPropertyEditor : PropertyEditorBase
|
||||
{
|
||||
public override FrameworkElement CreateElement(PropertyItem propertyItem)
|
||||
{
|
||||
var textbox = new System.Windows.Controls.TextBox
|
||||
{
|
||||
IsReadOnly = propertyItem.IsReadOnly
|
||||
};
|
||||
|
||||
textbox.SetBinding(System.Windows.Controls.TextBox.TextProperty, CreateBinding(propertyItem));
|
||||
|
||||
return textbox;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,8 +11,12 @@ namespace HandyControl.Controls
|
||||
new Binding(propertyItem.PropertyName)
|
||||
{
|
||||
Source = propertyItem.Value,
|
||||
Mode = propertyItem.IsReadOnly ? BindingMode.OneWay : BindingMode.TwoWay,
|
||||
UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
|
||||
Mode = GetBindingMode(),
|
||||
UpdateSourceTrigger = GetUpdateSourceTrigger()
|
||||
};
|
||||
|
||||
public virtual BindingMode GetBindingMode() => BindingMode.OneWay;
|
||||
|
||||
public virtual UpdateSourceTrigger GetUpdateSourceTrigger() => UpdateSourceTrigger.Default;
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace HandyControl.Controls
|
||||
{
|
||||
public class StringPropertyEditor : PropertyEditorBase
|
||||
public class PlainTextPropertyEditor : PropertyEditorBase
|
||||
{
|
||||
public override FrameworkElement CreateElement(PropertyItem propertyItem)
|
||||
{
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ using HandyControl.Tools;
|
||||
|
||||
namespace HandyControl.Controls
|
||||
{
|
||||
public class BooleanPropertyEditor : PropertyEditorBase
|
||||
public class SwitchPropertyEditor : PropertyEditorBase
|
||||
{
|
||||
public override FrameworkElement CreateElement(PropertyItem propertyItem)
|
||||
{
|
||||
@@ -0,0 +1,19 @@
|
||||
using System.Windows;
|
||||
|
||||
namespace HandyControl.Controls
|
||||
{
|
||||
public class TimePropertyEditor : PropertyEditorBase
|
||||
{
|
||||
public override FrameworkElement CreateElement(PropertyItem propertyItem)
|
||||
{
|
||||
var picker = new DateTimePicker
|
||||
{
|
||||
IsEnabled = !propertyItem.IsReadOnly
|
||||
};
|
||||
|
||||
picker.SetBinding(TimePicker.SelectedTimeProperty, CreateBinding(propertyItem));
|
||||
|
||||
return picker;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,20 +1,39 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
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));
|
||||
CommandBindings.Add(new CommandBinding(ControlCommands.SortByName, SortByName));
|
||||
}
|
||||
|
||||
public virtual PropertyResolver PropertyResolver { get; } = new PropertyResolver();
|
||||
|
||||
public static readonly RoutedEvent SelectedObjectChangedEvent =
|
||||
@@ -57,11 +76,41 @@ namespace HandyControl.Controls
|
||||
set => SetValue(DescriptionProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty MaxTitleWidthProperty = DependencyProperty.Register(
|
||||
"MaxTitleWidth", typeof(double), typeof(PropertyGrid), new PropertyMetadata(default(double)));
|
||||
|
||||
public double MaxTitleWidth
|
||||
{
|
||||
get => (double) GetValue(MaxTitleWidthProperty);
|
||||
set => SetValue(MaxTitleWidthProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty MinTitleWidthProperty = DependencyProperty.Register(
|
||||
"MinTitleWidth", typeof(double), typeof(PropertyGrid), new PropertyMetadata(default(double)));
|
||||
|
||||
public double MinTitleWidth
|
||||
{
|
||||
get => (double) GetValue(MinTitleWidthProperty);
|
||||
set => SetValue(MinTitleWidthProperty, 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);
|
||||
}
|
||||
|
||||
@@ -69,35 +118,73 @@ namespace HandyControl.Controls
|
||||
{
|
||||
if (obj == null || _itemsControl == null) return;
|
||||
|
||||
var type = obj.GetType();
|
||||
var propertyInfos = type.GetProperties();
|
||||
var itemList = propertyInfos.Select(CreatePropertyItem).Do(item => item.InitElement()).ToList();
|
||||
_itemsControl.ItemsSource = itemList;
|
||||
_dataView = CollectionViewSource.GetDefaultView(obj.GetType().GetProperties()
|
||||
.Where(item => PropertyResolver.ResolveBrowsable(item)).Select(CreatePropertyItem)
|
||||
.Do(item => item.InitElement()));
|
||||
|
||||
var categorySet = new HashSet<string>();
|
||||
foreach (var propertyItem in itemList)
|
||||
{
|
||||
categorySet.Add(propertyItem.Category);
|
||||
}
|
||||
|
||||
var view = CollectionViewSource.GetDefaultView(itemList);
|
||||
view.GroupDescriptions.Add(new PropertyGroupDescription("Category"));
|
||||
SortByCategory(null, null);
|
||||
_itemsControl.ItemsSource = _dataView;
|
||||
}
|
||||
|
||||
protected virtual PropertyItem CreatePropertyItem(PropertyInfo propertyInfo) =>
|
||||
new PropertyItem
|
||||
private void SortByCategory(object sender, ExecutedRoutedEventArgs e)
|
||||
{
|
||||
using (_dataView.DeferRefresh())
|
||||
{
|
||||
Category = PropertyResolver.ResolveCategory(propertyInfo),
|
||||
DisplayName = PropertyResolver.ResolveDisplayName(propertyInfo),
|
||||
Description = PropertyResolver.ResolveDescription(propertyInfo),
|
||||
Browsable = PropertyResolver.ResolveBrowsable(propertyInfo),
|
||||
IsReadOnly = PropertyResolver.ResolveIsReadOnly(propertyInfo),
|
||||
DefaultValue = PropertyResolver.ResolveDefaultValue(propertyInfo),
|
||||
Editor = PropertyResolver.ResolveEditor(propertyInfo),
|
||||
Converter = PropertyResolver.ResolveConverter(propertyInfo),
|
||||
Value = SelectedObject,
|
||||
PropertyName = propertyInfo.Name,
|
||||
PropertyTypeName = propertyInfo.PropertyType.FullName
|
||||
};
|
||||
_dataView.GroupDescriptions.Clear();
|
||||
_dataView.SortDescriptions.Clear();
|
||||
_dataView.SortDescriptions.Add(new SortDescription(PropertyItem.CategoryProperty.Name, ListSortDirection.Ascending));
|
||||
_dataView.SortDescriptions.Add(new SortDescription(PropertyItem.PropertyNameProperty.Name, ListSortDirection.Ascending));
|
||||
_dataView.GroupDescriptions.Add(new PropertyGroupDescription(PropertyItem.CategoryProperty.Name));
|
||||
}
|
||||
}
|
||||
|
||||
private void SortByName(object sender, ExecutedRoutedEventArgs e)
|
||||
{
|
||||
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)
|
||||
{
|
||||
_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(PropertyInfo propertyInfo) => new PropertyItem
|
||||
{
|
||||
Category = PropertyResolver.ResolveCategory(propertyInfo),
|
||||
DisplayName = PropertyResolver.ResolveDisplayName(propertyInfo),
|
||||
Description = PropertyResolver.ResolveDescription(propertyInfo),
|
||||
IsReadOnly = PropertyResolver.ResolveIsReadOnly(propertyInfo),
|
||||
DefaultValue = PropertyResolver.ResolveDefaultValue(propertyInfo),
|
||||
Editor = PropertyResolver.ResolveEditor(propertyInfo),
|
||||
Converter = PropertyResolver.ResolveConverter(propertyInfo),
|
||||
Value = SelectedObject,
|
||||
PropertyName = propertyInfo.Name,
|
||||
PropertyTypeName = propertyInfo.PropertyType.FullName
|
||||
};
|
||||
|
||||
protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
|
||||
{
|
||||
base.OnRenderSizeChanged(sizeInfo);
|
||||
TitleElement.SetTitleWidth(this, new GridLength(Math.Max(MinTitleWidth, Math.Min(MaxTitleWidth, ActualWidth / 3))));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -51,15 +51,6 @@ namespace HandyControl.Controls
|
||||
set => SetValue(DescriptionProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty BrowsableProperty = DependencyProperty.Register(
|
||||
"Browsable", typeof(bool), typeof(PropertyItem), new PropertyMetadata(default(bool)));
|
||||
|
||||
public bool Browsable
|
||||
{
|
||||
get => (bool)GetValue(BrowsableProperty);
|
||||
set => SetValue(BrowsableProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty IsReadOnlyProperty = DependencyProperty.Register(
|
||||
"IsReadOnly", typeof(bool), typeof(PropertyItem), new PropertyMetadata(default(bool)));
|
||||
|
||||
|
||||
@@ -25,7 +25,8 @@ namespace HandyControl.Controls
|
||||
[typeof(ulong)] = EditorTypeCode.UInt64Number,
|
||||
[typeof(float)] = EditorTypeCode.SingleNumber,
|
||||
[typeof(double)] = EditorTypeCode.DoubleNumber,
|
||||
[typeof(bool)] = EditorTypeCode.Switch
|
||||
[typeof(bool)] = EditorTypeCode.Switch,
|
||||
[typeof(DateTime)] = EditorTypeCode.DateTime
|
||||
};
|
||||
|
||||
public string ResolveCategory(PropertyInfo propertyInfo)
|
||||
@@ -121,24 +122,24 @@ namespace HandyControl.Controls
|
||||
TypeCodeDic.TryGetValue(type, out var editorType)
|
||||
? (PropertyEditorBase) (editorType switch
|
||||
{
|
||||
EditorTypeCode.PlainText => new StringPropertyEditor(),
|
||||
EditorTypeCode.SByteNumber => new IntegerPropertyEditor(sbyte.MinValue, sbyte.MaxValue),
|
||||
EditorTypeCode.ByteNumber => new IntegerPropertyEditor(byte.MinValue, byte.MaxValue),
|
||||
EditorTypeCode.Int16Number => new IntegerPropertyEditor(short.MinValue, short.MaxValue),
|
||||
EditorTypeCode.UInt16Number => new IntegerPropertyEditor(ushort.MinValue, ushort.MaxValue),
|
||||
EditorTypeCode.Int32Number => new IntegerPropertyEditor(int.MinValue, int.MaxValue),
|
||||
EditorTypeCode.UInt32Number => new IntegerPropertyEditor(uint.MinValue, uint.MaxValue),
|
||||
EditorTypeCode.Int64Number => new IntegerPropertyEditor(long.MinValue, long.MaxValue),
|
||||
EditorTypeCode.UInt64Number => new IntegerPropertyEditor(ulong.MinValue, ulong.MaxValue),
|
||||
EditorTypeCode.SingleNumber => new IntegerPropertyEditor(float.MinValue, float.MaxValue),
|
||||
EditorTypeCode.DoubleNumber => new IntegerPropertyEditor(double.MinValue, double.MaxValue),
|
||||
EditorTypeCode.Switch => new BooleanPropertyEditor(),
|
||||
EditorTypeCode.PlainText => new PlainTextPropertyEditor(),
|
||||
EditorTypeCode.SByteNumber => new NumberPropertyEditor(sbyte.MinValue, sbyte.MaxValue),
|
||||
EditorTypeCode.ByteNumber => new NumberPropertyEditor(byte.MinValue, byte.MaxValue),
|
||||
EditorTypeCode.Int16Number => new NumberPropertyEditor(short.MinValue, short.MaxValue),
|
||||
EditorTypeCode.UInt16Number => new NumberPropertyEditor(ushort.MinValue, ushort.MaxValue),
|
||||
EditorTypeCode.Int32Number => new NumberPropertyEditor(int.MinValue, int.MaxValue),
|
||||
EditorTypeCode.UInt32Number => new NumberPropertyEditor(uint.MinValue, uint.MaxValue),
|
||||
EditorTypeCode.Int64Number => new NumberPropertyEditor(long.MinValue, long.MaxValue),
|
||||
EditorTypeCode.UInt64Number => new NumberPropertyEditor(ulong.MinValue, ulong.MaxValue),
|
||||
EditorTypeCode.SingleNumber => new NumberPropertyEditor(float.MinValue, float.MaxValue),
|
||||
EditorTypeCode.DoubleNumber => new NumberPropertyEditor(double.MinValue, double.MaxValue),
|
||||
EditorTypeCode.Switch => new SwitchPropertyEditor(),
|
||||
EditorTypeCode.DateTime => new DateTimePropertyEditor(),
|
||||
_ => new StringPropertyEditor()
|
||||
_ => new PlainTextPropertyEditor()
|
||||
})
|
||||
: new StringPropertyEditor();
|
||||
: new PlainTextPropertyEditor();
|
||||
|
||||
public virtual PropertyEditorBase CreateEditor(Type type) => new StringPropertyEditor();
|
||||
public virtual PropertyEditorBase CreateEditor(Type type) => new PlainTextPropertyEditor();
|
||||
|
||||
private enum EditorTypeCode
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user