14 changed files with 1098 additions and 1 deletions
@ -0,0 +1,45 @@ |
|||
using System; |
|||
using System.Windows.Controls; |
|||
using System.Windows.Data; |
|||
using System.Windows; |
|||
|
|||
namespace Microsoft.Windows.Controls.PropertyGrid.Implementation.EditorProviders |
|||
{ |
|||
public class CheckBoxEditorProvider : ITypeEditorProvider |
|||
{ |
|||
CheckBox _checkbox; |
|||
|
|||
public CheckBoxEditorProvider() |
|||
{ |
|||
_checkbox = new CheckBox(); |
|||
_checkbox.Margin = new Thickness(2, 0, 0, 0); |
|||
} |
|||
|
|||
public void Initialize(PropertyItem propertyItem) |
|||
{ |
|||
ResolveBinding(propertyItem); |
|||
} |
|||
|
|||
public FrameworkElement ResolveEditor() |
|||
{ |
|||
return _checkbox; |
|||
} |
|||
|
|||
private void ResolveBinding(PropertyItem property) |
|||
{ |
|||
var binding = new Binding(property.Name); |
|||
binding.Source = property.Instance; |
|||
binding.ValidatesOnExceptions = true; |
|||
binding.ValidatesOnDataErrors = true; |
|||
|
|||
if (property.IsWriteable) |
|||
binding.Mode = BindingMode.TwoWay; |
|||
else |
|||
binding.Mode = BindingMode.OneWay; |
|||
|
|||
BindingOperations.SetBinding(_checkbox, CheckBox.IsCheckedProperty, binding); |
|||
} |
|||
|
|||
|
|||
} |
|||
} |
|||
@ -0,0 +1,67 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Windows.Controls; |
|||
using System.Windows; |
|||
using System.Windows.Data; |
|||
using System.Reflection; |
|||
|
|||
namespace Microsoft.Windows.Controls.PropertyGrid.Implementation.EditorProviders |
|||
{ |
|||
public class EnumComboBoxEditorProvider : ITypeEditorProvider |
|||
{ |
|||
ComboBox _comboBox; |
|||
|
|||
public EnumComboBoxEditorProvider() |
|||
{ |
|||
_comboBox = new ComboBox(); |
|||
} |
|||
|
|||
public void Initialize(PropertyItem propertyItem) |
|||
{ |
|||
ResolveBinding(propertyItem); |
|||
SetItemsSource(propertyItem); |
|||
} |
|||
|
|||
public FrameworkElement ResolveEditor() |
|||
{ |
|||
return _comboBox; |
|||
} |
|||
|
|||
private void ResolveBinding(PropertyItem property) |
|||
{ |
|||
var binding = new Binding(property.Name); |
|||
binding.Source = property.Instance; |
|||
binding.ValidatesOnExceptions = true; |
|||
binding.ValidatesOnDataErrors = true; |
|||
|
|||
if (property.IsWriteable) |
|||
binding.Mode = BindingMode.TwoWay; |
|||
else |
|||
binding.Mode = BindingMode.OneWay; |
|||
|
|||
BindingOperations.SetBinding(_comboBox, ComboBox.SelectedItemProperty, binding); |
|||
} |
|||
|
|||
private void SetItemsSource(PropertyItem property) |
|||
{ |
|||
_comboBox.ItemsSource = GetValues(property.PropertyType); |
|||
} |
|||
|
|||
public static object[] GetValues(Type enumType) |
|||
{ |
|||
List<object> values = new List<object>(); |
|||
|
|||
var fields = from field in enumType.GetFields() |
|||
where field.IsLiteral |
|||
select field; |
|||
|
|||
foreach (FieldInfo field in fields) |
|||
{ |
|||
values.Add(field.GetValue(enumType)); |
|||
} |
|||
|
|||
return values.ToArray(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,110 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Windows.Controls; |
|||
using System.Windows; |
|||
using System.Windows.Data; |
|||
using System.Windows.Media; |
|||
|
|||
namespace Microsoft.Windows.Controls.PropertyGrid.Implementation.EditorProviders |
|||
{ |
|||
public class FontComboBoxEditorProvider : ITypeEditorProvider |
|||
{ |
|||
ComboBox _comboBox; |
|||
|
|||
public FontComboBoxEditorProvider() |
|||
{ |
|||
_comboBox = new ComboBox(); |
|||
} |
|||
|
|||
public void Initialize(PropertyItem propertyItem) |
|||
{ |
|||
ResolveBinding(propertyItem); |
|||
SetItemsSource(propertyItem); |
|||
} |
|||
|
|||
public FrameworkElement ResolveEditor() |
|||
{ |
|||
return _comboBox; |
|||
} |
|||
|
|||
private void ResolveBinding(PropertyItem property) |
|||
{ |
|||
var binding = new Binding(property.Name); |
|||
binding.Source = property.Instance; |
|||
binding.ValidatesOnExceptions = true; |
|||
binding.ValidatesOnDataErrors = true; |
|||
|
|||
if (property.IsWriteable) |
|||
binding.Mode = BindingMode.TwoWay; |
|||
else |
|||
binding.Mode = BindingMode.OneWay; |
|||
|
|||
BindingOperations.SetBinding(_comboBox, ComboBox.SelectedItemProperty, binding); |
|||
} |
|||
|
|||
private void SetItemsSource(PropertyItem property) |
|||
{ |
|||
if (property.PropertyType == typeof(FontFamily)) |
|||
{ |
|||
List<FontFamily> fonts = new List<FontFamily>(); |
|||
fonts.Add(new FontFamily("Arial")); |
|||
fonts.Add(new FontFamily("Courier New")); |
|||
fonts.Add(new FontFamily("Times New Roman")); |
|||
fonts.Add(new FontFamily("Batang")); |
|||
fonts.Add(new FontFamily("BatangChe")); |
|||
fonts.Add(new FontFamily("DFKai-SB")); |
|||
fonts.Add(new FontFamily("Dotum")); |
|||
fonts.Add(new FontFamily("DutumChe")); |
|||
fonts.Add(new FontFamily("FangSong")); |
|||
fonts.Add(new FontFamily("GulimChe")); |
|||
fonts.Add(new FontFamily("Gungsuh")); |
|||
fonts.Add(new FontFamily("GungsuhChe")); |
|||
fonts.Add(new FontFamily("KaiTi")); |
|||
fonts.Add(new FontFamily("Malgun Gothic")); |
|||
fonts.Add(new FontFamily("Meiryo")); |
|||
fonts.Add(new FontFamily("Microsoft JhengHei")); |
|||
fonts.Add(new FontFamily("Microsoft YaHei")); |
|||
fonts.Add(new FontFamily("MingLiU")); |
|||
fonts.Add(new FontFamily("MingLiu_HKSCS")); |
|||
fonts.Add(new FontFamily("MingLiu_HKSCS-ExtB")); |
|||
fonts.Add(new FontFamily("MingLiu-ExtB")); |
|||
_comboBox.ItemsSource = fonts; |
|||
} |
|||
else if (property.PropertyType == typeof(FontWeight)) |
|||
{ |
|||
List<FontWeight> list = new List<FontWeight>() |
|||
{ |
|||
FontWeights.Black, FontWeights.Bold, FontWeights.ExtraBlack, FontWeights.ExtraBold, |
|||
FontWeights.ExtraLight, FontWeights.Light, FontWeights.Medium, FontWeights.Normal, FontWeights.SemiBold, |
|||
FontWeights.Thin |
|||
}; |
|||
_comboBox.ItemsSource = list; |
|||
} |
|||
else if (property.PropertyType == typeof(FontStyle)) |
|||
{ |
|||
List<FontStyle> list = new List<FontStyle>() |
|||
{ |
|||
FontStyles.Italic, |
|||
FontStyles.Normal |
|||
}; |
|||
_comboBox.ItemsSource = list; |
|||
} |
|||
else if (property.PropertyType == typeof(FontStretch)) |
|||
{ |
|||
List<FontStretch> list = new List<FontStretch>() |
|||
{ |
|||
FontStretches.Condensed, |
|||
FontStretches.Expanded, |
|||
FontStretches.ExtraCondensed, |
|||
FontStretches.ExtraExpanded, |
|||
FontStretches.Normal, |
|||
FontStretches.SemiCondensed, |
|||
FontStretches.SemiExpanded, |
|||
FontStretches.UltraCondensed, |
|||
FontStretches.UltraExpanded |
|||
}; |
|||
_comboBox.ItemsSource = list; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,11 @@ |
|||
using System; |
|||
using System.Windows; |
|||
|
|||
namespace Microsoft.Windows.Controls.PropertyGrid.Implementation.EditorProviders |
|||
{ |
|||
interface ITypeEditorProvider |
|||
{ |
|||
void Initialize(PropertyItem propertyItem); |
|||
FrameworkElement ResolveEditor(); |
|||
} |
|||
} |
|||
@ -0,0 +1,41 @@ |
|||
using System; |
|||
using System.Windows.Data; |
|||
using System.Windows; |
|||
|
|||
namespace Microsoft.Windows.Controls.PropertyGrid.Implementation.EditorProviders |
|||
{ |
|||
public class NumericUpDownEditorProvider : ITypeEditorProvider |
|||
{ |
|||
NumericUpDown _numericUpDown; |
|||
|
|||
public NumericUpDownEditorProvider() |
|||
{ |
|||
_numericUpDown = new NumericUpDown(); |
|||
} |
|||
|
|||
public void Initialize(PropertyItem propertyItem) |
|||
{ |
|||
ResolveBinding(propertyItem); |
|||
} |
|||
|
|||
public FrameworkElement ResolveEditor() |
|||
{ |
|||
return _numericUpDown; |
|||
} |
|||
|
|||
private void ResolveBinding(PropertyItem property) |
|||
{ |
|||
var binding = new Binding(property.Name); |
|||
binding.Source = property.Instance; |
|||
binding.ValidatesOnExceptions = true; |
|||
binding.ValidatesOnDataErrors = true; |
|||
|
|||
if (property.IsWriteable) |
|||
binding.Mode = BindingMode.TwoWay; |
|||
else |
|||
binding.Mode = BindingMode.OneWay; |
|||
|
|||
BindingOperations.SetBinding(_numericUpDown, NumericUpDown.ValueProperty, binding); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,42 @@ |
|||
using System; |
|||
using System.Windows.Controls; |
|||
using System.Windows.Data; |
|||
using System.Windows; |
|||
|
|||
namespace Microsoft.Windows.Controls.PropertyGrid.Implementation.EditorProviders |
|||
{ |
|||
public class TextBoxEditorProvider : ITypeEditorProvider |
|||
{ |
|||
FrameworkElement _editor; |
|||
|
|||
public TextBoxEditorProvider() |
|||
{ |
|||
_editor = new TextBox(); |
|||
} |
|||
|
|||
public void Initialize(PropertyItem propertyItem) |
|||
{ |
|||
ResolveBinding(propertyItem); |
|||
} |
|||
|
|||
public FrameworkElement ResolveEditor() |
|||
{ |
|||
return _editor; |
|||
} |
|||
|
|||
private void ResolveBinding(PropertyItem property) |
|||
{ |
|||
var binding = new Binding(property.Name); |
|||
binding.Source = property.Instance; |
|||
binding.ValidatesOnExceptions = true; |
|||
binding.ValidatesOnDataErrors = true; |
|||
|
|||
if (property.IsWriteable) |
|||
binding.Mode = BindingMode.TwoWay; |
|||
else |
|||
binding.Mode = BindingMode.OneWay; |
|||
|
|||
BindingOperations.SetBinding(_editor, TextBox.TextProperty, binding); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,72 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Windows.Controls; |
|||
using System.Windows; |
|||
|
|||
namespace Microsoft.Windows.Controls.PropertyGrid |
|||
{ |
|||
public class PropertyCategoryItem : Control |
|||
{ |
|||
public static readonly DependencyProperty CategoryProperty = DependencyProperty.Register("Category", typeof(string), typeof(PropertyCategoryItem), new UIPropertyMetadata(String.Empty, new PropertyChangedCallback(OnCategoryChanged), new CoerceValueCallback(OnCoerceCategory))); |
|||
|
|||
private static object OnCoerceCategory(DependencyObject o, object value) |
|||
{ |
|||
PropertyCategoryItem propertyCategoryItem = o as PropertyCategoryItem; |
|||
if (propertyCategoryItem != null) |
|||
return propertyCategoryItem.OnCoerceCategory((string)value); |
|||
else |
|||
return value; |
|||
} |
|||
|
|||
private static void OnCategoryChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) |
|||
{ |
|||
PropertyCategoryItem propertyCategoryItem = o as PropertyCategoryItem; |
|||
if (propertyCategoryItem != null) |
|||
propertyCategoryItem.OnCategoryChanged((string)e.OldValue, (string)e.NewValue); |
|||
} |
|||
|
|||
protected virtual string OnCoerceCategory(string value) |
|||
{ |
|||
// TODO: Keep the proposed value within the desired range.
|
|||
return value; |
|||
} |
|||
|
|||
protected virtual void OnCategoryChanged(string oldValue, string newValue) |
|||
{ |
|||
// TODO: Add your property changed side-effects. Descendants can override as well.
|
|||
} |
|||
|
|||
public string Category |
|||
{ |
|||
// IMPORTANT: To maintain parity between setting a property in XAML and procedural code, do not touch the getter and setter inside this dependency property!
|
|||
get |
|||
{ |
|||
return (string)GetValue(CategoryProperty); |
|||
} |
|||
set |
|||
{ |
|||
SetValue(CategoryProperty, value); |
|||
} |
|||
} |
|||
|
|||
|
|||
private List<PropertyItem> _Properties = new List<PropertyItem>(); |
|||
public List<PropertyItem> Properties |
|||
{ |
|||
get |
|||
{ |
|||
return _Properties; |
|||
} |
|||
set |
|||
{ |
|||
_Properties = value; |
|||
} |
|||
} |
|||
|
|||
|
|||
static PropertyCategoryItem() |
|||
{ |
|||
DefaultStyleKeyProperty.OverrideMetadata(typeof(PropertyCategoryItem), new FrameworkPropertyMetadata(typeof(PropertyCategoryItem))); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,24 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Collections.ObjectModel; |
|||
|
|||
namespace Microsoft.Windows.Controls.PropertyGrid |
|||
{ |
|||
public class PropertyCollection : ObservableCollection<object> |
|||
{ |
|||
public PropertyCollection() |
|||
{ |
|||
|
|||
} |
|||
public PropertyCollection(List<object> list) |
|||
: base(list) |
|||
{ |
|||
|
|||
} |
|||
public PropertyCollection(IEnumerable<object> collection) |
|||
: base(collection) |
|||
{ |
|||
|
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,323 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Windows; |
|||
using System.Windows.Controls; |
|||
using System.Windows.Data; |
|||
using System.Windows.Media; |
|||
using System.Windows.Controls.Primitives; |
|||
using System.ComponentModel; |
|||
using Microsoft.Windows.Controls.PropertyGrid.Implementation.EditorProviders; |
|||
|
|||
namespace Microsoft.Windows.Controls.PropertyGrid |
|||
{ |
|||
public class PropertyGrid : Control |
|||
{ |
|||
#region Members
|
|||
|
|||
private Thumb _dragThumb; |
|||
private List<PropertyItem> _propertyItemsCache; |
|||
|
|||
#endregion //Members
|
|||
|
|||
#region Properties
|
|||
|
|||
#region IsCategorized
|
|||
|
|||
public static readonly DependencyProperty IsCategorizedProperty = DependencyProperty.Register("IsCategorized", typeof(bool), typeof(PropertyGrid), new UIPropertyMetadata(true, OnIsCategorizedChanged)); |
|||
public bool IsCategorized |
|||
{ |
|||
get { return (bool)GetValue(IsCategorizedProperty); } |
|||
set { SetValue(IsCategorizedProperty, value); } |
|||
} |
|||
|
|||
private static void OnIsCategorizedChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) |
|||
{ |
|||
PropertyGrid propertyGrid = o as PropertyGrid; |
|||
if (propertyGrid != null) |
|||
propertyGrid.OnIsCategorizedChanged((bool)e.OldValue, (bool)e.NewValue); |
|||
} |
|||
|
|||
protected virtual void OnIsCategorizedChanged(bool oldValue, bool newValue) |
|||
{ |
|||
LoadProperties(newValue); |
|||
} |
|||
|
|||
#endregion //IsCategorized
|
|||
|
|||
#region NameWidth
|
|||
|
|||
public static readonly DependencyProperty NameWidthProperty = DependencyProperty.Register("NameWidth", typeof(double), typeof(PropertyGrid), new UIPropertyMetadata(120.0, OnNameWidthChanged)); |
|||
public double NameWidth |
|||
{ |
|||
get { return (double)GetValue(NameWidthProperty); } |
|||
set { SetValue(NameWidthProperty, value); } |
|||
} |
|||
|
|||
private static void OnNameWidthChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) |
|||
{ |
|||
PropertyGrid propertyGrid = o as PropertyGrid; |
|||
if (propertyGrid != null) |
|||
propertyGrid.OnNameWidthChanged((double)e.OldValue, (double)e.NewValue); |
|||
} |
|||
|
|||
protected virtual void OnNameWidthChanged(double oldValue, double newValue) |
|||
{ |
|||
// TODO: Add your property changed side-effects. Descendants can override as well.
|
|||
} |
|||
|
|||
#endregion //NameWidth
|
|||
|
|||
#region Properties
|
|||
|
|||
public static readonly DependencyProperty PropertiesProperty = DependencyProperty.Register("Properties", typeof(PropertyCollection), typeof(PropertyGrid), new UIPropertyMetadata(null, OnPropertiesChanged)); |
|||
public PropertyCollection Properties |
|||
{ |
|||
get { return (PropertyCollection)GetValue(PropertiesProperty); } |
|||
private set { SetValue(PropertiesProperty, value); } |
|||
} |
|||
|
|||
private static void OnPropertiesChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) |
|||
{ |
|||
PropertyGrid propertyGrid = o as PropertyGrid; |
|||
if (propertyGrid != null) |
|||
propertyGrid.OnPropertiesChanged((PropertyCollection)e.OldValue, (PropertyCollection)e.NewValue); |
|||
} |
|||
|
|||
protected virtual void OnPropertiesChanged(PropertyCollection oldValue, PropertyCollection newValue) |
|||
{ |
|||
// TODO: Add your property changed side-effects. Descendants can override as well.
|
|||
} |
|||
|
|||
#endregion //Properties
|
|||
|
|||
#region SelectedObject
|
|||
|
|||
public static readonly DependencyProperty SelectedObjectProperty = DependencyProperty.Register("SelectedObject", typeof(object), typeof(PropertyGrid), new UIPropertyMetadata(null, OnSelectedObjectChanged)); |
|||
public object SelectedObject |
|||
{ |
|||
get { return (object)GetValue(SelectedObjectProperty); } |
|||
set { SetValue(SelectedObjectProperty, value); } |
|||
} |
|||
|
|||
private static void OnSelectedObjectChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) |
|||
{ |
|||
PropertyGrid propertyInspector = o as PropertyGrid; |
|||
if (propertyInspector != null) |
|||
propertyInspector.OnSelectedObjectChanged((object)e.OldValue, (object)e.NewValue); |
|||
} |
|||
|
|||
protected virtual void OnSelectedObjectChanged(object oldValue, object newValue) |
|||
{ |
|||
SelectedObjectType = newValue.GetType(); |
|||
|
|||
if (newValue is FrameworkElement) |
|||
SelectedObjectName = (newValue as FrameworkElement).Name; |
|||
|
|||
_propertyItemsCache = GetObjectProperties(newValue); |
|||
|
|||
LoadProperties(IsCategorized); |
|||
} |
|||
|
|||
#endregion //SelectedObject
|
|||
|
|||
#region SelectedObjectType
|
|||
|
|||
public static readonly DependencyProperty SelectedObjectTypeProperty = DependencyProperty.Register("SelectedObjectType", typeof(Type), typeof(PropertyGrid), new UIPropertyMetadata(null, OnSelectedObjectTypeChanged)); |
|||
public Type SelectedObjectType |
|||
{ |
|||
get { return (Type)GetValue(SelectedObjectTypeProperty); } |
|||
set { SetValue(SelectedObjectTypeProperty, value); } |
|||
} |
|||
|
|||
private static void OnSelectedObjectTypeChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) |
|||
{ |
|||
PropertyGrid propertyGrid = o as PropertyGrid; |
|||
if (propertyGrid != null) |
|||
propertyGrid.OnSelectedObjectTypeChanged((Type)e.OldValue, (Type)e.NewValue); |
|||
} |
|||
|
|||
protected virtual void OnSelectedObjectTypeChanged(Type oldValue, Type newValue) |
|||
{ |
|||
SelectedObjectTypeName = newValue.Name; |
|||
} |
|||
|
|||
#endregion //SelectedObjectType
|
|||
|
|||
#region SelectedObjectTypeName
|
|||
|
|||
public static readonly DependencyProperty SelectedObjectTypeNameProperty = DependencyProperty.Register("SelectedObjectTypeName", typeof(string), typeof(PropertyGrid), new UIPropertyMetadata(string.Empty, OnSelectedObjectTypeNameChanged)); |
|||
public string SelectedObjectTypeName |
|||
{ |
|||
get { return (string)GetValue(SelectedObjectTypeNameProperty); } |
|||
set { SetValue(SelectedObjectTypeNameProperty, value); } |
|||
} |
|||
|
|||
private static void OnSelectedObjectTypeNameChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) |
|||
{ |
|||
PropertyGrid propertyGrid = o as PropertyGrid; |
|||
if (propertyGrid != null) |
|||
propertyGrid.OnSelectedObjectTypeNameChanged((string)e.OldValue, (string)e.NewValue); |
|||
} |
|||
|
|||
protected virtual void OnSelectedObjectTypeNameChanged(string oldValue, string newValue) |
|||
{ |
|||
// TODO: Add your property changed side-effects. Descendants can override as well.
|
|||
} |
|||
|
|||
#endregion //SelectedObjectTypeName
|
|||
|
|||
#region SelectedObjectName
|
|||
|
|||
public static readonly DependencyProperty SelectedObjectNameProperty = DependencyProperty.Register("SelectedObjectName", typeof(string), typeof(PropertyGrid), new UIPropertyMetadata(string.Empty, OnSelectedObjectNameChanged)); |
|||
public string SelectedObjectName |
|||
{ |
|||
get { return (string)GetValue(SelectedObjectNameProperty); } |
|||
set { SetValue(SelectedObjectNameProperty, value); } |
|||
} |
|||
|
|||
private static void OnSelectedObjectNameChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) |
|||
{ |
|||
PropertyGrid propertyGrid = o as PropertyGrid; |
|||
if (propertyGrid != null) |
|||
propertyGrid.OnSelectedObjectNameChanged((string)e.OldValue, (string)e.NewValue); |
|||
} |
|||
|
|||
protected virtual void OnSelectedObjectNameChanged(string oldValue, string newValue) |
|||
{ |
|||
// TODO: Add your property changed side-effects. Descendants can override as well.
|
|||
} |
|||
|
|||
#endregion //SelectedObjectName
|
|||
|
|||
#endregion //Properties
|
|||
|
|||
#region Constructors
|
|||
|
|||
static PropertyGrid() |
|||
{ |
|||
DefaultStyleKeyProperty.OverrideMetadata(typeof(PropertyGrid), new FrameworkPropertyMetadata(typeof(PropertyGrid))); |
|||
} |
|||
|
|||
#endregion //Constructors
|
|||
|
|||
#region Base Class Overrides
|
|||
|
|||
public override void OnApplyTemplate() |
|||
{ |
|||
base.OnApplyTemplate(); |
|||
|
|||
_dragThumb = (Thumb)GetTemplateChild("PART_DragThumb"); |
|||
_dragThumb.DragDelta += DragThumb_DragDelta; |
|||
} |
|||
|
|||
#endregion //Base Class Overrides
|
|||
|
|||
#region Event Handlers
|
|||
|
|||
void DragThumb_DragDelta(object sender, DragDeltaEventArgs e) |
|||
{ |
|||
NameWidth = Math.Max(0, NameWidth + e.HorizontalChange); |
|||
} |
|||
|
|||
#endregion //Event Handlers
|
|||
|
|||
#region Methods
|
|||
|
|||
private void LoadProperties(bool isCategorized) |
|||
{ |
|||
if (isCategorized) |
|||
Properties = GetCategorizedProperties(_propertyItemsCache); |
|||
else |
|||
Properties = GetAlphabetizedProperties(_propertyItemsCache); |
|||
} |
|||
|
|||
private static List<PropertyItem> GetObjectProperties(object instance) |
|||
{ |
|||
var propertyItems = new List<PropertyItem>(); |
|||
if (instance == null) |
|||
return propertyItems; |
|||
|
|||
var properties = TypeDescriptor.GetProperties(instance.GetType(), new Attribute[] { new PropertyFilterAttribute(PropertyFilterOptions.All) }); |
|||
|
|||
// Get all properties of the type
|
|||
propertyItems.AddRange(properties.Cast<PropertyDescriptor>(). |
|||
Where(p => p.IsBrowsable && p.Name != "GenericParameterAttributes"). |
|||
Select(property => CreatePropertyItem(property, instance))); |
|||
|
|||
return propertyItems; |
|||
} |
|||
|
|||
private static PropertyItem CreatePropertyItem(PropertyDescriptor property, object instance) |
|||
{ |
|||
PropertyItem propertyItem = new PropertyItem(instance, property); |
|||
ITypeEditorProvider editorProvider = null; |
|||
|
|||
if (propertyItem.PropertyType == typeof(string)) |
|||
editorProvider = new TextBoxEditorProvider(); |
|||
else if (propertyItem.PropertyType == typeof(bool)) |
|||
editorProvider = new CheckBoxEditorProvider(); |
|||
else if (propertyItem.PropertyType.IsEnum) |
|||
editorProvider = new EnumComboBoxEditorProvider(); |
|||
else if (propertyItem.PropertyType == typeof(FontFamily) || propertyItem.PropertyType == typeof(FontWeight) || propertyItem.PropertyType == typeof(FontStyle) || propertyItem.PropertyType == typeof(FontStretch)) |
|||
editorProvider = new FontComboBoxEditorProvider(); |
|||
else if (propertyItem.PropertyType == typeof(double)) |
|||
editorProvider = new TextBoxEditorProvider(); |
|||
else if (propertyItem.PropertyType == typeof(object) || propertyItem.PropertyType == typeof(Thickness)) |
|||
editorProvider = new TextBoxEditorProvider(); |
|||
|
|||
if (editorProvider != null) |
|||
{ |
|||
editorProvider.Initialize(propertyItem); |
|||
propertyItem.Editor = editorProvider.ResolveEditor(); |
|||
} |
|||
|
|||
return propertyItem; |
|||
} |
|||
|
|||
private PropertyCollection GetCategorizedProperties(List<PropertyItem> propertyItems) |
|||
{ |
|||
PropertyCollection propertyCollection = new PropertyCollection(); |
|||
|
|||
CollectionViewSource src = new CollectionViewSource(); |
|||
src.Source = propertyItems; |
|||
src.GroupDescriptions.Add(new PropertyGroupDescription("Category")); |
|||
src.SortDescriptions.Add(new SortDescription("Category", ListSortDirection.Ascending)); |
|||
src.SortDescriptions.Add(new SortDescription("Name", ListSortDirection.Ascending)); |
|||
|
|||
foreach (CollectionViewGroup item in src.View.Groups) |
|||
{ |
|||
PropertyCategoryItem propertyCategoryItem = new PropertyCategoryItem(); |
|||
propertyCategoryItem.Category = item.Name.ToString(); |
|||
foreach (var propertyitem in item.Items) |
|||
{ |
|||
propertyCategoryItem.Properties.Add((PropertyItem)propertyitem); |
|||
} |
|||
propertyCollection.Add(propertyCategoryItem); |
|||
} |
|||
|
|||
return propertyCollection; |
|||
} |
|||
|
|||
private PropertyCollection GetAlphabetizedProperties(List<PropertyItem> propertyItems) |
|||
{ |
|||
PropertyCollection propertyCollection = new PropertyCollection(); |
|||
|
|||
if (propertyItems == null) |
|||
return propertyCollection; |
|||
|
|||
CollectionViewSource src = new CollectionViewSource(); |
|||
src.Source = propertyItems; |
|||
src.SortDescriptions.Add(new SortDescription("Name", ListSortDirection.Ascending)); |
|||
|
|||
foreach (var item in ((ListCollectionView)(src.View))) |
|||
{ |
|||
propertyCollection.Add((PropertyItem)item); |
|||
} |
|||
|
|||
return propertyCollection; |
|||
} |
|||
|
|||
#endregion //Methods
|
|||
} |
|||
} |
|||
@ -0,0 +1,140 @@ |
|||
using System; |
|||
using System.Windows.Controls; |
|||
using System.ComponentModel; |
|||
using System.Windows; |
|||
|
|||
namespace Microsoft.Windows.Controls.PropertyGrid |
|||
{ |
|||
public class PropertyItem : Control |
|||
{ |
|||
#region Members
|
|||
|
|||
public object Instance { get; private set; } |
|||
public PropertyDescriptor PropertyDescriptor { get; private set; } |
|||
|
|||
#endregion //Members
|
|||
|
|||
#region Properties
|
|||
|
|||
public string Description |
|||
{ |
|||
get { return PropertyDescriptor.Description; } |
|||
} |
|||
|
|||
public bool IsWriteable |
|||
{ |
|||
get { return !IsReadOnly; } |
|||
} |
|||
|
|||
public bool IsReadOnly |
|||
{ |
|||
get { return PropertyDescriptor.IsReadOnly; } |
|||
} |
|||
|
|||
public Type PropertyType |
|||
{ |
|||
get { return PropertyDescriptor.PropertyType; } |
|||
} |
|||
|
|||
//public string Category
|
|||
//{
|
|||
// get { return PropertyDescriptor.Category; }
|
|||
//}
|
|||
|
|||
public static readonly DependencyProperty CategoryProperty = DependencyProperty.Register("Category", typeof(string), typeof(PropertyItem), new UIPropertyMetadata(string.Empty, new PropertyChangedCallback(OnCategoryChanged), new CoerceValueCallback(OnCoerceCategory))); |
|||
|
|||
private static object OnCoerceCategory(DependencyObject o, object value) |
|||
{ |
|||
PropertyItem propertyItem = o as PropertyItem; |
|||
if (propertyItem != null) |
|||
return propertyItem.OnCoerceCategory((string)value); |
|||
else |
|||
return value; |
|||
} |
|||
|
|||
private static void OnCategoryChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) |
|||
{ |
|||
PropertyItem propertyItem = o as PropertyItem; |
|||
if (propertyItem != null) |
|||
propertyItem.OnCategoryChanged((string)e.OldValue, (string)e.NewValue); |
|||
} |
|||
|
|||
protected virtual string OnCoerceCategory(string value) |
|||
{ |
|||
// TODO: Keep the proposed value within the desired range.
|
|||
return value; |
|||
} |
|||
|
|||
protected virtual void OnCategoryChanged(string oldValue, string newValue) |
|||
{ |
|||
// TODO: Add your property changed side-effects. Descendants can override as well.
|
|||
} |
|||
|
|||
public string Category |
|||
{ |
|||
// IMPORTANT: To maintain parity between setting a property in XAML and procedural code, do not touch the getter and setter inside this dependency property!
|
|||
get |
|||
{ |
|||
return (string)GetValue(CategoryProperty); |
|||
} |
|||
set |
|||
{ |
|||
SetValue(CategoryProperty, value); |
|||
} |
|||
} |
|||
|
|||
|
|||
#region Editor
|
|||
|
|||
public static readonly DependencyProperty EditorProperty = DependencyProperty.Register("Editor", typeof(FrameworkElement), typeof(PropertyItem), new UIPropertyMetadata(null, OnEditorChanged)); |
|||
public FrameworkElement Editor |
|||
{ |
|||
get { return (FrameworkElement)GetValue(EditorProperty); } |
|||
set { SetValue(EditorProperty, value); } |
|||
} |
|||
|
|||
private static void OnEditorChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) |
|||
{ |
|||
PropertyItem propertyItem = o as PropertyItem; |
|||
if (propertyItem != null) |
|||
propertyItem.OnEditorChanged((FrameworkElement)e.OldValue, (FrameworkElement)e.NewValue); |
|||
} |
|||
|
|||
protected virtual void OnEditorChanged(FrameworkElement oldValue, FrameworkElement newValue) |
|||
{ |
|||
// TODO: Add your property changed side-effects. Descendants can override as well.
|
|||
} |
|||
|
|||
#endregion //Editor
|
|||
|
|||
#endregion //Properties
|
|||
|
|||
#region Constructor
|
|||
|
|||
static PropertyItem() |
|||
{ |
|||
DefaultStyleKeyProperty.OverrideMetadata(typeof(PropertyItem), new FrameworkPropertyMetadata(typeof(PropertyItem))); |
|||
} |
|||
|
|||
public PropertyItem(object instance, PropertyDescriptor property) |
|||
{ |
|||
Instance = instance; |
|||
PropertyDescriptor = property; |
|||
Name = PropertyDescriptor.Name; |
|||
Category = PropertyDescriptor.Category; |
|||
} |
|||
|
|||
#endregion //Constructor
|
|||
|
|||
#region INotifyPropertyChanged Members
|
|||
|
|||
public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; |
|||
protected void OnPropertyChanged(string propertyName) |
|||
{ |
|||
if (PropertyChanged != null) |
|||
PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); |
|||
} |
|||
|
|||
#endregion
|
|||
} |
|||
} |
|||
@ -0,0 +1,202 @@ |
|||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
|||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
|||
xmlns:local="clr-namespace:Microsoft.Windows.Controls.PropertyGrid" |
|||
xmlns:converters="clr-namespace:Microsoft.Windows.Controls.Core.Converters"> |
|||
|
|||
<!-- =============================================================================== --> |
|||
<!-- PropertyGrid --> |
|||
<!-- =============================================================================== --> |
|||
|
|||
<converters:InverseBoolConverter x:Key="InverseBoolConverter" /> |
|||
|
|||
<SolidColorBrush x:Key="GlyphBrush" Color="#FF31347C"/> |
|||
|
|||
<ControlTemplate x:Key="ExpanderToggleButton" TargetType="{x:Type ToggleButton}"> |
|||
<Grid> |
|||
<Rectangle Margin="0,0,0,0" x:Name="Rectangle" Fill="Transparent" /> |
|||
<Path HorizontalAlignment="Center" x:Name="Up_Arrow" VerticalAlignment="Center" Fill="{StaticResource GlyphBrush}" Data="M 0 0 L 4 4 L 8 0 Z" RenderTransformOrigin="0.5,0.5"> |
|||
<Path.RenderTransform> |
|||
<TransformGroup> |
|||
<ScaleTransform ScaleX="1" ScaleY="1" /> |
|||
<SkewTransform AngleX="0" AngleY="0" /> |
|||
<RotateTransform Angle="-90" /> |
|||
<TranslateTransform X="0" Y="0" /> |
|||
</TransformGroup> |
|||
</Path.RenderTransform> |
|||
</Path> |
|||
<Path Visibility="Collapsed" HorizontalAlignment="Center" x:Name="Down_Arrow" VerticalAlignment="Center" Fill="{StaticResource GlyphBrush}" Data="M 0 4 L 4 0 L 8 4 Z" RenderTransformOrigin="0.5,0.5"> |
|||
<Path.RenderTransform> |
|||
<TransformGroup> |
|||
<ScaleTransform ScaleX="1" ScaleY="1" /> |
|||
<SkewTransform AngleX="0" AngleY="0" /> |
|||
<RotateTransform Angle="135" /> |
|||
<TranslateTransform X="0" Y="0" /> |
|||
</TransformGroup> |
|||
</Path.RenderTransform> |
|||
</Path> |
|||
</Grid> |
|||
<ControlTemplate.Triggers> |
|||
<Trigger Property="IsChecked" Value="true"> |
|||
<Setter Property="Visibility" Value="Visible" TargetName="Down_Arrow" /> |
|||
<Setter Property="Visibility" Value="Collapsed" TargetName="Up_Arrow" /> |
|||
<Setter Property="OpacityMask" TargetName="Down_Arrow" Value="#FF000000" /> |
|||
</Trigger> |
|||
</ControlTemplate.Triggers> |
|||
</ControlTemplate> |
|||
|
|||
<Style x:Key="ExpanderStyle" TargetType="{x:Type Expander}"> |
|||
<Setter Property="Padding" Value="0" /> |
|||
<Setter Property="Background" Value="#FFF0F0F0" /> |
|||
<Setter Property="Template"> |
|||
<Setter.Value> |
|||
<ControlTemplate TargetType="{x:Type Expander}"> |
|||
<Grid> |
|||
<Grid.RowDefinitions> |
|||
<RowDefinition Height="Auto" /> |
|||
<RowDefinition Height="*" x:Name="ContentRow" /> |
|||
</Grid.RowDefinitions> |
|||
<Border x:Name="Border" Background="{TemplateBinding Background}" BorderBrush="#FFF0F0F0"> |
|||
<Grid> |
|||
<Grid.ColumnDefinitions> |
|||
<ColumnDefinition Width="20" /> |
|||
<ColumnDefinition Width="*" /> |
|||
</Grid.ColumnDefinitions> |
|||
<ToggleButton Template="{StaticResource ExpanderToggleButton}" IsChecked="{Binding Path=IsExpanded, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" OverridesDefaultStyle="True" /> |
|||
<ContentPresenter Grid.Column="1" Margin="1" RecognizesAccessKey="True" ContentSource="Header" TextElement.FontWeight="Bold" /> |
|||
</Grid> |
|||
</Border> |
|||
<Border Visibility="Collapsed" Grid.Row="1" x:Name="ExpandSite" Background="#FFF0F0F0" Padding="10 0 0 0"> |
|||
|
|||
<Border Background="#FFFFFF" BorderThickness="0" Margin="0" Padding="0" VerticalAlignment="Stretch" HorizontalAlignment="Stretch"> |
|||
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Focusable="false" /> |
|||
</Border> |
|||
|
|||
</Border> |
|||
</Grid> |
|||
<ControlTemplate.Triggers> |
|||
<Trigger Property="IsExpanded" Value="True"> |
|||
<Setter Property="Visibility" Value="Visible" TargetName="ExpandSite" /> |
|||
</Trigger> |
|||
</ControlTemplate.Triggers> |
|||
</ControlTemplate> |
|||
</Setter.Value> |
|||
</Setter> |
|||
</Style> |
|||
|
|||
<Style TargetType="{x:Type local:PropertyCategoryItem}"> |
|||
<Setter Property="Template"> |
|||
<Setter.Value> |
|||
<ControlTemplate TargetType="{x:Type local:PropertyCategoryItem}"> |
|||
<Border Background="{TemplateBinding Background}" |
|||
BorderBrush="{TemplateBinding BorderBrush}" |
|||
BorderThickness="{TemplateBinding BorderThickness}"> |
|||
<Expander Header="{TemplateBinding Category}" Style="{StaticResource ExpanderStyle}" IsExpanded="True"> |
|||
<ItemsControl ItemsSource="{Binding Properties, RelativeSource={RelativeSource TemplatedParent}}" /> |
|||
</Expander> |
|||
</Border> |
|||
</ControlTemplate> |
|||
</Setter.Value> |
|||
</Setter> |
|||
</Style> |
|||
|
|||
<Style TargetType="{x:Type local:PropertyItem}"> |
|||
<Setter Property="BorderBrush" Value="#FFF0F0F0" /> |
|||
<Setter Property="BorderThickness" Value="1" /> |
|||
<Setter Property="Template"> |
|||
<Setter.Value> |
|||
<ControlTemplate TargetType="{x:Type local:PropertyItem}"> |
|||
<Border> |
|||
<Grid VerticalAlignment="Center" HorizontalAlignment="Stretch"> |
|||
<Grid.ColumnDefinitions> |
|||
<ColumnDefinition Width="{Binding NameWidth, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:PropertyGrid}}}"/> |
|||
<ColumnDefinition Width="*"/> |
|||
</Grid.ColumnDefinitions> |
|||
|
|||
<Border BorderThickness="0.5" BorderBrush="#FFF0F0F0" x:Name="PART_Name"> |
|||
<TextBlock Text="{Binding Name, RelativeSource={RelativeSource TemplatedParent}}" Margin="7,2,0,2"/> |
|||
</Border> |
|||
|
|||
<Border BorderThickness="0.5" BorderBrush="#FFF0F0F0" x:Name="PART_Editor" Grid.Column="1" Background="Transparent"> |
|||
<ContentControl Content="{TemplateBinding Editor}" VerticalAlignment="Center" /> |
|||
</Border> |
|||
</Grid> |
|||
</Border> |
|||
</ControlTemplate> |
|||
</Setter.Value> |
|||
</Setter> |
|||
</Style> |
|||
|
|||
<Style TargetType="{x:Type local:PropertyGrid}"> |
|||
<Setter Property="Background" Value="#CED4DF" /> |
|||
<Setter Property="BorderBrush" Value="#43577B" /> |
|||
<Setter Property="BorderThickness" Value="1" /> |
|||
<Setter Property="Template"> |
|||
<Setter.Value> |
|||
<ControlTemplate TargetType="{x:Type local:PropertyGrid}"> |
|||
<Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"> |
|||
<Grid> |
|||
<Grid.RowDefinitions> |
|||
<RowDefinition Height="Auto"/> |
|||
<RowDefinition Height="Auto" /> |
|||
<RowDefinition /> |
|||
<RowDefinition Height="5" /> |
|||
<RowDefinition Height="Auto"/> |
|||
</Grid.RowDefinitions> |
|||
|
|||
<StackPanel Orientation="Horizontal" Margin="6,2,0,4"> |
|||
<TextBlock Text="{TemplateBinding SelectedObjectTypeName}" FontWeight="Bold"/> |
|||
<TextBlock Width="6">:</TextBlock> |
|||
<TextBlock Text="{TemplateBinding SelectedObjectName}" /> |
|||
</StackPanel> |
|||
|
|||
<Grid Grid.Row="1" Margin="4,0,4,4"> |
|||
<Grid.ColumnDefinitions> |
|||
<ColumnDefinition Width="Auto"/> |
|||
<ColumnDefinition Width="*"/> |
|||
</Grid.ColumnDefinitions> |
|||
<Grid Background="#BCC7D8" Margin="4"> |
|||
<StackPanel Orientation="Horizontal" Margin="2" > |
|||
<RadioButton IsChecked="{Binding IsCategorized, RelativeSource={RelativeSource TemplatedParent}}" VerticalAlignment="Center" /> |
|||
<RadioButton IsChecked="{Binding IsCategorized, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource InverseBoolConverter}, Mode=OneWay}" VerticalAlignment="Center"/> |
|||
</StackPanel> |
|||
</Grid> |
|||
<TextBox Grid.Column="1" Text="Not Implemented" Margin="4" Opacity=".5" /> |
|||
</Grid> |
|||
|
|||
<Grid Grid.Row="2" Background="White"> |
|||
<ScrollViewer VerticalScrollBarVisibility="Auto"> |
|||
<ItemsControl ItemsSource="{Binding Properties, RelativeSource={RelativeSource TemplatedParent}}" > |
|||
<ItemsControl.ItemsPanel> |
|||
<ItemsPanelTemplate> |
|||
<VirtualizingStackPanel /> |
|||
</ItemsPanelTemplate> |
|||
</ItemsControl.ItemsPanel> |
|||
</ItemsControl> |
|||
</ScrollViewer> |
|||
|
|||
<Thumb x:Name="PART_DragThumb" HorizontalAlignment="Left" Width="5" Margin="6,0,0,0" Cursor="SizeWE"> |
|||
<Thumb.RenderTransform> |
|||
<TranslateTransform X="{Binding NameWidth, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:PropertyGrid}}}" /> |
|||
</Thumb.RenderTransform> |
|||
<Thumb.Template> |
|||
<ControlTemplate> |
|||
<Border Background="Transparent" /> |
|||
</ControlTemplate> |
|||
</Thumb.Template> |
|||
</Thumb> |
|||
|
|||
</Grid> |
|||
|
|||
<GridSplitter Height="3" Grid.Row="3" HorizontalAlignment="Stretch" /> |
|||
<StackPanel Grid.Row="4" Margin="0,0,0,5"> |
|||
<TextBlock Padding="2 2 2 0" FontWeight="Bold" Text="Property Name" /> |
|||
<TextBlock Padding="5 2 2 0" TextWrapping="WrapWithOverflow" Text="Property Description" /> |
|||
</StackPanel> |
|||
</Grid> |
|||
</Border> |
|||
</ControlTemplate> |
|||
</Setter.Value> |
|||
</Setter> |
|||
</Style> |
|||
|
|||
</ResourceDictionary> |
|||
Loading…
Reference in new issue