add partial codes
This commit is contained in:
1 parent
507a44aa25
commit
aeb5d2a3b8
37 files changed
+806
-4
No files matched your search
@@ -0,0 +1,23 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Controls.Primitives;
|
||||
using HandyControl.Tools;
|
||||
|
||||
namespace HandyControl.Controls
|
||||
{
|
||||
public class BooleanPropertyEditor : PropertyEditorBase
|
||||
{
|
||||
public override FrameworkElement CreateElement(PropertyItem propertyItem)
|
||||
{
|
||||
var button = new ToggleButton
|
||||
{
|
||||
Style = ResourceHelper.GetResource<Style>("ToggleButtonSwitch"),
|
||||
HorizontalAlignment = HorizontalAlignment.Left,
|
||||
IsEnabled = !propertyItem.IsReadOnly
|
||||
};
|
||||
|
||||
button.SetBinding(ToggleButton.IsCheckedProperty, CreateBinding(propertyItem));
|
||||
|
||||
return button;
|
||||
}
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
using System.Windows;
|
||||
|
||||
namespace HandyControl.Controls
|
||||
{
|
||||
public class DateTimePropertyEditor : PropertyEditorBase
|
||||
{
|
||||
public override FrameworkElement CreateElement(PropertyItem propertyItem)
|
||||
{
|
||||
var picker = new DateTimePicker
|
||||
{
|
||||
IsEnabled = !propertyItem.IsReadOnly
|
||||
};
|
||||
|
||||
picker.SetBinding(DateTimePicker.SelectedDateTimeProperty, CreateBinding(propertyItem));
|
||||
|
||||
return picker;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using System.Windows;
|
||||
|
||||
namespace HandyControl.Controls
|
||||
{
|
||||
public class IntegerPropertyEditor : PropertyEditorBase
|
||||
{
|
||||
public IntegerPropertyEditor(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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace HandyControl.Controls
|
||||
{
|
||||
public abstract class PropertyEditorBase : FrameworkElement
|
||||
{
|
||||
public abstract FrameworkElement CreateElement(PropertyItem propertyItem);
|
||||
|
||||
public virtual Binding CreateBinding(PropertyItem propertyItem) =>
|
||||
new Binding(propertyItem.PropertyName)
|
||||
{
|
||||
Source = propertyItem.Value,
|
||||
Mode = propertyItem.IsReadOnly ? BindingMode.OneWay : BindingMode.TwoWay,
|
||||
UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using System.Windows;
|
||||
|
||||
namespace HandyControl.Controls
|
||||
{
|
||||
public class StringPropertyEditor : 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using HandyControl.Tools.Extension;
|
||||
|
||||
namespace HandyControl.Controls
|
||||
{
|
||||
[TemplatePart(Name = ElementItemsControl, Type = typeof(ItemsControl))]
|
||||
public class PropertyGrid : Control
|
||||
{
|
||||
private const string ElementItemsControl = "PART_ItemsControl";
|
||||
|
||||
private ItemsControl _itemsControl;
|
||||
|
||||
public virtual PropertyResolver PropertyResolver { get; } = new PropertyResolver();
|
||||
|
||||
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(
|
||||
"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(
|
||||
"Description", typeof(string), typeof(PropertyGrid), new PropertyMetadata(default(string)));
|
||||
|
||||
public string Description
|
||||
{
|
||||
get => (string)GetValue(DescriptionProperty);
|
||||
set => SetValue(DescriptionProperty, value);
|
||||
}
|
||||
|
||||
public override void OnApplyTemplate()
|
||||
{
|
||||
base.OnApplyTemplate();
|
||||
|
||||
_itemsControl = GetTemplateChild(ElementItemsControl) as ItemsControl;
|
||||
UpdateItems(SelectedObject);
|
||||
}
|
||||
|
||||
private void UpdateItems(object obj)
|
||||
{
|
||||
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;
|
||||
|
||||
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"));
|
||||
}
|
||||
|
||||
protected virtual PropertyItem CreatePropertyItem(PropertyInfo propertyInfo) =>
|
||||
new PropertyItem
|
||||
{
|
||||
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
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace HandyControl.Controls
|
||||
{
|
||||
public class PropertyItem : Control
|
||||
{
|
||||
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(
|
||||
"Value", typeof(object), typeof(PropertyItem), new PropertyMetadata(default(object)));
|
||||
|
||||
public object Value
|
||||
{
|
||||
get => GetValue(ValueProperty);
|
||||
set => SetValue(ValueProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty DisplayNameProperty = DependencyProperty.Register(
|
||||
"DisplayName", typeof(string), typeof(PropertyItem), new PropertyMetadata(default(string)));
|
||||
|
||||
public string DisplayName
|
||||
{
|
||||
get => (string)GetValue(DisplayNameProperty);
|
||||
set => SetValue(DisplayNameProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty PropertyNameProperty = DependencyProperty.Register(
|
||||
"PropertyName", typeof(string), typeof(PropertyItem), new PropertyMetadata(default(string)));
|
||||
|
||||
public string PropertyName
|
||||
{
|
||||
get => (string)GetValue(PropertyNameProperty);
|
||||
set => SetValue(PropertyNameProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty PropertyTypeNameProperty = DependencyProperty.Register(
|
||||
"PropertyTypeName", typeof(string), typeof(PropertyItem), new PropertyMetadata(default(string)));
|
||||
|
||||
public string PropertyTypeName
|
||||
{
|
||||
get => (string)GetValue(PropertyTypeNameProperty);
|
||||
set => SetValue(PropertyTypeNameProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty DescriptionProperty = DependencyProperty.Register(
|
||||
"Description", typeof(string), typeof(PropertyItem), new PropertyMetadata(default(string)));
|
||||
|
||||
public string Description
|
||||
{
|
||||
get => (string)GetValue(DescriptionProperty);
|
||||
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)));
|
||||
|
||||
public bool IsReadOnly
|
||||
{
|
||||
get => (bool)GetValue(IsReadOnlyProperty);
|
||||
set => SetValue(IsReadOnlyProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty DefaultValueProperty = DependencyProperty.Register(
|
||||
"DefaultValue", typeof(object), typeof(PropertyItem), new PropertyMetadata(default(object)));
|
||||
|
||||
public object DefaultValue
|
||||
{
|
||||
get => GetValue(DefaultValueProperty);
|
||||
set => SetValue(DefaultValueProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty CategoryProperty = DependencyProperty.Register(
|
||||
"Category", typeof(string), typeof(PropertyItem), new PropertyMetadata(default(string)));
|
||||
|
||||
public string Category
|
||||
{
|
||||
get => (string)GetValue(CategoryProperty);
|
||||
set => SetValue(CategoryProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty EditorProperty = DependencyProperty.Register(
|
||||
"Editor", typeof(PropertyEditorBase), typeof(PropertyItem), new PropertyMetadata(default(PropertyEditorBase)));
|
||||
|
||||
public PropertyEditorBase Editor
|
||||
{
|
||||
get => (PropertyEditorBase)GetValue(EditorProperty);
|
||||
set => SetValue(EditorProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty EditorElementProperty = DependencyProperty.Register(
|
||||
"EditorElement", typeof(FrameworkElement), typeof(PropertyItem), new PropertyMetadata(default(FrameworkElement)));
|
||||
|
||||
public FrameworkElement EditorElement
|
||||
{
|
||||
get => (FrameworkElement)GetValue(EditorElementProperty);
|
||||
set => SetValue(EditorElementProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty IsSelectedProperty = DependencyProperty.Register(
|
||||
"IsSelected", typeof(bool), typeof(PropertyItem), new PropertyMetadata(default(bool)));
|
||||
|
||||
public bool IsSelected
|
||||
{
|
||||
get => (bool)GetValue(IsSelectedProperty);
|
||||
set => SetValue(IsSelectedProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty IsExpandedEnabledProperty = DependencyProperty.Register(
|
||||
"IsExpandedEnabled", typeof(bool), typeof(PropertyItem), new PropertyMetadata(default(bool)));
|
||||
|
||||
public bool IsExpandedEnabled
|
||||
{
|
||||
get => (bool)GetValue(IsExpandedEnabledProperty);
|
||||
set => SetValue(IsExpandedEnabledProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ConverterProperty = DependencyProperty.Register(
|
||||
"Converter", typeof(IValueConverter), typeof(PropertyItem), new PropertyMetadata(default(IValueConverter)));
|
||||
|
||||
public IValueConverter Converter
|
||||
{
|
||||
get => (IValueConverter) GetValue(ConverterProperty);
|
||||
set => SetValue(ConverterProperty, value);
|
||||
}
|
||||
|
||||
public virtual void InitElement()
|
||||
{
|
||||
if (Editor == null) return;
|
||||
EditorElement = Editor.CreateElement(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace HandyControl.Controls
|
||||
{
|
||||
public class PropertyItemsControl : ItemsControl
|
||||
{
|
||||
protected override bool IsItemItsOwnContainerOverride(object item) => item is PropertyItem;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Reflection;
|
||||
using System.Windows.Data;
|
||||
using HandyControl.Properties.Langs;
|
||||
#if NET40
|
||||
using HandyControl.Tools.Extension;
|
||||
#endif
|
||||
|
||||
namespace HandyControl.Controls
|
||||
{
|
||||
public class PropertyResolver
|
||||
{
|
||||
private static readonly Dictionary<Type, EditorTypeCode> TypeCodeDic = new Dictionary<Type, EditorTypeCode>
|
||||
{
|
||||
[typeof(string)] = EditorTypeCode.PlainText,
|
||||
[typeof(sbyte)] = EditorTypeCode.SByteNumber,
|
||||
[typeof(byte)] = EditorTypeCode.ByteNumber,
|
||||
[typeof(short)] = EditorTypeCode.Int16Number,
|
||||
[typeof(ushort)] = EditorTypeCode.UInt16Number,
|
||||
[typeof(int)] = EditorTypeCode.Int32Number,
|
||||
[typeof(uint)] = EditorTypeCode.UInt32Number,
|
||||
[typeof(long)] = EditorTypeCode.Int64Number,
|
||||
[typeof(ulong)] = EditorTypeCode.UInt64Number,
|
||||
[typeof(float)] = EditorTypeCode.SingleNumber,
|
||||
[typeof(double)] = EditorTypeCode.DoubleNumber,
|
||||
[typeof(bool)] = EditorTypeCode.Switch
|
||||
};
|
||||
|
||||
public string ResolveCategory(PropertyInfo propertyInfo)
|
||||
{
|
||||
var categoryAttribute = propertyInfo.GetCustomAttribute<CategoryAttribute>();
|
||||
string category;
|
||||
if (categoryAttribute != null && !string.IsNullOrEmpty(categoryAttribute.Category))
|
||||
{
|
||||
category = categoryAttribute.Category;
|
||||
}
|
||||
else
|
||||
{
|
||||
category = Lang.Miscellaneous;
|
||||
}
|
||||
|
||||
return category;
|
||||
}
|
||||
|
||||
public string ResolveDisplayName(PropertyInfo propertyInfo)
|
||||
{
|
||||
var displayNameAttribute = propertyInfo.GetCustomAttribute<DisplayNameAttribute>();
|
||||
string displayName;
|
||||
if (displayNameAttribute != null && !string.IsNullOrEmpty(displayNameAttribute.DisplayName))
|
||||
{
|
||||
displayName = displayNameAttribute.DisplayName;
|
||||
}
|
||||
else
|
||||
{
|
||||
displayName = propertyInfo.Name;
|
||||
}
|
||||
|
||||
return displayName;
|
||||
}
|
||||
|
||||
public string ResolveDescription(PropertyInfo propertyInfo)
|
||||
{
|
||||
var descriptionAttribute = propertyInfo.GetCustomAttribute<DescriptionAttribute>();
|
||||
string description;
|
||||
if (descriptionAttribute != null && !string.IsNullOrEmpty(descriptionAttribute.Description))
|
||||
{
|
||||
description = descriptionAttribute.Description;
|
||||
}
|
||||
else
|
||||
{
|
||||
description = string.Empty;
|
||||
}
|
||||
|
||||
return description;
|
||||
}
|
||||
|
||||
public bool ResolveBrowsable(PropertyInfo propertyInfo)
|
||||
{
|
||||
var browsableAttribute = propertyInfo.GetCustomAttribute<BrowsableAttribute>();
|
||||
return browsableAttribute == null || browsableAttribute.Browsable;
|
||||
}
|
||||
|
||||
public bool ResolveIsReadOnly(PropertyInfo propertyInfo)
|
||||
{
|
||||
var isReadOnlyAttribute = propertyInfo.GetCustomAttribute<ReadOnlyAttribute>();
|
||||
return isReadOnlyAttribute != null && isReadOnlyAttribute.IsReadOnly;
|
||||
}
|
||||
|
||||
public object ResolveDefaultValue(PropertyInfo propertyInfo)
|
||||
{
|
||||
var defaultValueAttribute = propertyInfo.GetCustomAttribute<DefaultValueAttribute>();
|
||||
return defaultValueAttribute?.Value;
|
||||
}
|
||||
|
||||
public IValueConverter ResolveConverter(PropertyInfo propertyInfo)
|
||||
{
|
||||
var typeConverterAttribute = propertyInfo.GetCustomAttribute<TypeConverterAttribute>();
|
||||
if (typeConverterAttribute != null && !string.IsNullOrEmpty(typeConverterAttribute.ConverterTypeName))
|
||||
{
|
||||
return CreateTypeConverter(Type.GetType(typeConverterAttribute.ConverterTypeName));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public virtual IValueConverter CreateTypeConverter(Type type) => Activator.CreateInstance(type) as IValueConverter;
|
||||
|
||||
public PropertyEditorBase ResolveEditor(PropertyInfo propertyInfo)
|
||||
{
|
||||
var editorAttribute = propertyInfo.GetCustomAttribute<EditorAttribute>();
|
||||
var editor = editorAttribute == null || string.IsNullOrEmpty(editorAttribute.EditorTypeName)
|
||||
? CreateDefaultEditor(propertyInfo.PropertyType)
|
||||
: CreateEditor(Type.GetType(editorAttribute.EditorTypeName));
|
||||
|
||||
return editor;
|
||||
}
|
||||
|
||||
public virtual PropertyEditorBase CreateDefaultEditor(Type type) =>
|
||||
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.DateTime => new DateTimePropertyEditor(),
|
||||
_ => new StringPropertyEditor()
|
||||
})
|
||||
: new StringPropertyEditor();
|
||||
|
||||
public virtual PropertyEditorBase CreateEditor(Type type) => new StringPropertyEditor();
|
||||
|
||||
private enum EditorTypeCode
|
||||
{
|
||||
PlainText,
|
||||
SByteNumber,
|
||||
ByteNumber,
|
||||
Int16Number,
|
||||
UInt16Number,
|
||||
Int32Number,
|
||||
UInt32Number,
|
||||
Int64Number,
|
||||
UInt64Number,
|
||||
SingleNumber,
|
||||
DoubleNumber,
|
||||
Switch,
|
||||
DateTime
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user