diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Properties/AssemblyInfo.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Properties/AssemblyInfo.cs index 70ce5a49..854114b6 100644 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Properties/AssemblyInfo.cs +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Properties/AssemblyInfo.cs @@ -60,3 +60,4 @@ using System.Windows.Markup; [assembly: XmlnsPrefix("http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit/extended", "extToolkit")] [assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit/extended", "Microsoft.Windows.Controls")] +[assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit/extended", "Microsoft.Windows.Controls.PropertyGrid")] diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/EditorProviders/CheckBoxEditorProvider.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/EditorProviders/CheckBoxEditorProvider.cs new file mode 100644 index 00000000..4d80b084 --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/EditorProviders/CheckBoxEditorProvider.cs @@ -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); + } + + + } +} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/EditorProviders/EnumComboBoxEditorProvider.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/EditorProviders/EnumComboBoxEditorProvider.cs new file mode 100644 index 00000000..17301263 --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/EditorProviders/EnumComboBoxEditorProvider.cs @@ -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 values = new List(); + + 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(); + } + } +} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/EditorProviders/FontComboBoxEditorProvider.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/EditorProviders/FontComboBoxEditorProvider.cs new file mode 100644 index 00000000..a6c06394 --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/EditorProviders/FontComboBoxEditorProvider.cs @@ -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 fonts = new List(); + 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 list = new List() + { + 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 list = new List() + { + FontStyles.Italic, + FontStyles.Normal + }; + _comboBox.ItemsSource = list; + } + else if (property.PropertyType == typeof(FontStretch)) + { + List list = new List() + { + FontStretches.Condensed, + FontStretches.Expanded, + FontStretches.ExtraCondensed, + FontStretches.ExtraExpanded, + FontStretches.Normal, + FontStretches.SemiCondensed, + FontStretches.SemiExpanded, + FontStretches.UltraCondensed, + FontStretches.UltraExpanded + }; + _comboBox.ItemsSource = list; + } + } + } +} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/EditorProviders/ITypeEditorProvider.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/EditorProviders/ITypeEditorProvider.cs new file mode 100644 index 00000000..5c629e96 --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/EditorProviders/ITypeEditorProvider.cs @@ -0,0 +1,11 @@ +using System; +using System.Windows; + +namespace Microsoft.Windows.Controls.PropertyGrid.Implementation.EditorProviders +{ + interface ITypeEditorProvider + { + void Initialize(PropertyItem propertyItem); + FrameworkElement ResolveEditor(); + } +} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/EditorProviders/NumericUpDownEditorProvider.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/EditorProviders/NumericUpDownEditorProvider.cs new file mode 100644 index 00000000..8dd8a3d6 --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/EditorProviders/NumericUpDownEditorProvider.cs @@ -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); + } + } +} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/EditorProviders/TextBoxEditorProvider.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/EditorProviders/TextBoxEditorProvider.cs new file mode 100644 index 00000000..c475713d --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/EditorProviders/TextBoxEditorProvider.cs @@ -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); + } + } +} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/PropertyCategoryItem.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/PropertyCategoryItem.cs new file mode 100644 index 00000000..27089598 --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/PropertyCategoryItem.cs @@ -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 _Properties = new List(); + public List Properties + { + get + { + return _Properties; + } + set + { + _Properties = value; + } + } + + + static PropertyCategoryItem() + { + DefaultStyleKeyProperty.OverrideMetadata(typeof(PropertyCategoryItem), new FrameworkPropertyMetadata(typeof(PropertyCategoryItem))); + } + } +} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/PropertyCollection.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/PropertyCollection.cs new file mode 100644 index 00000000..95834089 --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/PropertyCollection.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; + +namespace Microsoft.Windows.Controls.PropertyGrid +{ + public class PropertyCollection : ObservableCollection + { + public PropertyCollection() + { + + } + public PropertyCollection(List list) + : base(list) + { + + } + public PropertyCollection(IEnumerable collection) + : base(collection) + { + + } + } +} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/PropertyGrid.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/PropertyGrid.cs new file mode 100644 index 00000000..d0d2650f --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/PropertyGrid.cs @@ -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 _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 GetObjectProperties(object instance) + { + var propertyItems = new List(); + 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(). + 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 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 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 + } +} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/PropertyItem.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/PropertyItem.cs new file mode 100644 index 00000000..74c5eff3 --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/PropertyItem.cs @@ -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 + } +} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Themes/Generic.xaml b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Themes/Generic.xaml new file mode 100644 index 00000000..bd546678 --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Themes/Generic.xaml @@ -0,0 +1,202 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Themes/Generic.xaml b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Themes/Generic.xaml index 1dfe5ec1..bf9cb6f9 100644 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Themes/Generic.xaml +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Themes/Generic.xaml @@ -12,5 +12,8 @@ + + + diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/WPFToolkit.Extended.csproj b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/WPFToolkit.Extended.csproj index 5d20e02d..f0a7f868 100644 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/WPFToolkit.Extended.csproj +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/WPFToolkit.Extended.csproj @@ -99,6 +99,10 @@ Designer MSBuild:Compile + + Designer + MSBuild:Compile + Designer MSBuild:Compile @@ -160,6 +164,16 @@ True + + + + + + + + + + RichTextBoxFormatBar.xaml @@ -223,7 +237,9 @@ - + + +