diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Utilities/ContextMenuUtilities.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Utilities/ContextMenuUtilities.cs new file mode 100644 index 00000000..7c317640 --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Utilities/ContextMenuUtilities.cs @@ -0,0 +1,35 @@ +using System; +using System.Windows; + +namespace Microsoft.Windows.Controls.Core.Utilities +{ + public class ContextMenuUtilities + { + public static readonly DependencyProperty OpenOnMouseLeftButtonClickProperty = DependencyProperty.RegisterAttached("OpenOnMouseLeftButtonClick", typeof(bool), typeof(FrameworkElement), new FrameworkPropertyMetadata(false, OpenOnMouseLeftButtonClickChanged)); + public static void SetOpenOnMouseLeftButtonClick(FrameworkElement element, bool value) + { + element.SetValue(OpenOnMouseLeftButtonClickProperty, value); + } + public static bool GetOpenOnMouseLeftButtonClick(FrameworkElement element) + { + return (bool)element.GetValue(OpenOnMouseLeftButtonClickProperty); + } + + public static void OpenOnMouseLeftButtonClickChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) + { + var control = (FrameworkElement)sender; + if ((bool)e.NewValue) + { + control.PreviewMouseLeftButtonDown += (s, args) => + { + if (control.ContextMenu != null) + { + control.ContextMenu.PlacementTarget = control; + control.ContextMenu.IsOpen = true; + } + }; + } + //TODO: remove handler when set to false + } + } +} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Images/AdvancedProperties11.png b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Images/AdvancedProperties11.png new file mode 100644 index 00000000..0146e932 Binary files /dev/null and b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Images/AdvancedProperties11.png differ diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Images/Database11.png b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Images/Database11.png new file mode 100644 index 00000000..0f523fbd Binary files /dev/null and b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Images/Database11.png differ diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Images/Inheritance11.png b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Images/Inheritance11.png new file mode 100644 index 00000000..7dd3b491 Binary files /dev/null and b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Images/Inheritance11.png differ diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Images/Local11.png b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Images/Local11.png new file mode 100644 index 00000000..ec521dd4 Binary files /dev/null and b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Images/Local11.png differ diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Images/Resource11.png b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Images/Resource11.png new file mode 100644 index 00000000..7275c981 Binary files /dev/null and b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Images/Resource11.png differ diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Images/Style11.png b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Images/Style11.png new file mode 100644 index 00000000..7a6005d6 Binary files /dev/null and b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Images/Style11.png differ diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/Commands/PropertyItemCommands.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/Commands/PropertyItemCommands.cs new file mode 100644 index 00000000..f1db5ce6 --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/Commands/PropertyItemCommands.cs @@ -0,0 +1,17 @@ +using System; +using System.Windows.Input; + +namespace Microsoft.Windows.Controls.PropertyGrid.Commands +{ + public static class PropertyItemCommands + { + private static RoutedCommand _resetValueCommand = new RoutedCommand(); + public static RoutedCommand ResetValue + { + get + { + return _resetValueCommand; + } + } + } +} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/Converters/ValueSourceToImagePathConverter.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/Converters/ValueSourceToImagePathConverter.cs new file mode 100644 index 00000000..51aadbb7 --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/Converters/ValueSourceToImagePathConverter.cs @@ -0,0 +1,48 @@ +using System; +using System.Windows; +using System.Windows.Data; +using System.Windows.Media.Imaging; + +namespace Microsoft.Windows.Controls.PropertyGrid.Converters +{ + public class ValueSourceToImagePathConverter : IValueConverter + { + #region IValueConverter Members + + public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + BaseValueSource bvs = (BaseValueSource)value; + + string uriPrefix = "/WPFToolkit.Extended;component/PropertyGrid/Images/"; + string imageName = "AdvancedProperties11"; + + switch (bvs) + { + case BaseValueSource.Inherited: + case BaseValueSource.DefaultStyle: + case BaseValueSource.ImplicitStyleReference: + imageName = "Inheritance11"; + break; + case BaseValueSource.DefaultStyleTrigger: + break; + case BaseValueSource.Style: + imageName = "Style11"; + break; + + case BaseValueSource.Local: + imageName = "Local11"; + break; + } + + + return new BitmapImage(new Uri(String.Format("{0}{1}.png", uriPrefix, imageName), UriKind.RelativeOrAbsolute)); + } + + public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + throw new NotImplementedException(); + } + + #endregion + } +} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/Converters/ValueSourceToToolTipConverter.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/Converters/ValueSourceToToolTipConverter.cs new file mode 100644 index 00000000..2b70c134 --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/Converters/ValueSourceToToolTipConverter.cs @@ -0,0 +1,42 @@ +using System; +using System.Windows; +using System.Windows.Data; + +namespace Microsoft.Windows.Controls.PropertyGrid.Converters +{ + class ValueSourceToToolTipConverter : IValueConverter + { + #region IValueConverter Members + + public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + BaseValueSource bvs = (BaseValueSource)value; + string toolTip = "Advanced Properties"; + + switch (bvs) + { + case BaseValueSource.Inherited: + case BaseValueSource.DefaultStyle: + case BaseValueSource.ImplicitStyleReference: + toolTip = "Inheritance"; + break; + case BaseValueSource.Style: + toolTip = "Style Setter"; + break; + + case BaseValueSource.Local: + toolTip = "Local"; + break; + } + + return toolTip; + } + + public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + throw new NotImplementedException(); + } + + #endregion + } +} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/PropertyItem.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/PropertyItem.cs index 382b10f9..fa3f2be7 100644 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/PropertyItem.cs +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/PropertyItem.cs @@ -1,8 +1,12 @@ using System; -using System.Windows.Controls; +using System.Linq; using System.ComponentModel; using System.Windows; +using System.Windows.Controls; using System.Windows.Data; +using System.Windows.Input; +using Microsoft.Windows.Controls.PropertyGrid.Commands; +using System.Windows.Markup.Primitives; namespace Microsoft.Windows.Controls.PropertyGrid { @@ -11,6 +15,7 @@ namespace Microsoft.Windows.Controls.PropertyGrid #region Members private DependencyPropertyDescriptor _dpDescriptor; + private MarkupObject _markupObject; #endregion //Members @@ -29,7 +34,30 @@ namespace Microsoft.Windows.Controls.PropertyGrid public string Description { get { return PropertyDescriptor.Description; } } - public object Instance { get; private set; } + #region Editor + + public static readonly DependencyProperty EditorProperty = DependencyProperty.Register("Editor", typeof(FrameworkElement), typeof(PropertyItem), new UIPropertyMetadata(null)); + public FrameworkElement Editor + { + get { return (FrameworkElement)GetValue(EditorProperty); } + set { SetValue(EditorProperty, value); } + } + + #endregion //Editor + + private object _instance; + public object Instance + { + get + { + return _instance; + } + private set + { + _instance = value; + _markupObject = MarkupWriter.GetMarkupObjectFor(_instance); + } + } /// /// Gets if the property is data bound @@ -46,6 +74,30 @@ namespace Microsoft.Windows.Controls.PropertyGrid } } + public bool IsDynamicResource + { + get + { + var markupProperty = _markupObject.Properties.Where(p => p.Name == PropertyDescriptor.Name).FirstOrDefault(); + if (markupProperty != null) + return markupProperty.Value is DynamicResourceExtension; + return false; + } + } + + public bool HasResourceApplied + { + //TODO: need to find a better way to determine if a StaticResource has been applied to any property not just a style + get + { + var markupProperty = _markupObject.Properties.Where(p => p.Name == PropertyDescriptor.Name).FirstOrDefault(); + if (markupProperty != null) + return markupProperty.Value is Style; + + return false; + } + } + public bool IsReadOnly { get { return PropertyDescriptor.IsReadOnly; } } #region IsSelected @@ -74,41 +126,37 @@ namespace Microsoft.Windows.Controls.PropertyGrid public bool IsWriteable { get { return !IsReadOnly; } } - public PropertyDescriptor PropertyDescriptor { get; private set; } + private PropertyDescriptor _propertyDescriptor; + public PropertyDescriptor PropertyDescriptor + { + get + { + return _propertyDescriptor; + } + private set + { + _propertyDescriptor = value; + Name = _propertyDescriptor.Name; + Category = _propertyDescriptor.Category; + _dpDescriptor = DependencyPropertyDescriptor.FromProperty(_propertyDescriptor); + } + } public PropertyGrid PropertyGrid { get; private set; } public Type PropertyType { get { return PropertyDescriptor.PropertyType; } } - #region Editor - - public static readonly DependencyProperty EditorProperty = DependencyProperty.Register("Editor", typeof(FrameworkElement), typeof(PropertyItem), new UIPropertyMetadata(null)); - public FrameworkElement Editor - { - get { return (FrameworkElement)GetValue(EditorProperty); } - set { SetValue(EditorProperty, value); } - } - - #endregion //Editor + public ICommand ResetValueCommand { get; private set; } #region Value - public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(object), typeof(PropertyItem), new UIPropertyMetadata(null, new PropertyChangedCallback(OnValueChanged), new CoerceValueCallback(OnCoerceValue))); + public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(object), typeof(PropertyItem), new UIPropertyMetadata(null, OnValueChanged)); public object Value { get { return (object)GetValue(ValueProperty); } set { SetValue(ValueProperty, value); } } - private static object OnCoerceValue(DependencyObject o, object value) - { - PropertyItem propertyItem = o as PropertyItem; - if (propertyItem != null) - return propertyItem.OnCoerceValue((object)value); - else - return value; - } - private static void OnValueChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) { PropertyItem propertyItem = o as PropertyItem; @@ -116,16 +164,10 @@ namespace Microsoft.Windows.Controls.PropertyGrid propertyItem.OnValueChanged((object)e.OldValue, (object)e.NewValue); } - protected virtual object OnCoerceValue(object value) - { - // TODO: Keep the proposed value within the desired range. - return value; - } - protected virtual void OnValueChanged(object oldValue, object newValue) { // TODO: Add your property changed side-effects. Descendants can override as well. - } + } #endregion //Value @@ -155,29 +197,62 @@ namespace Microsoft.Windows.Controls.PropertyGrid public PropertyItem(object instance, PropertyDescriptor property, PropertyGrid propertyGrid) { - Instance = instance; + PropertyDescriptor = property; - Name = PropertyDescriptor.Name; - Category = PropertyDescriptor.Category; PropertyGrid = propertyGrid; + Instance = instance; - _dpDescriptor = DependencyPropertyDescriptor.FromProperty(property); + CommandBindings.Add(new CommandBinding(PropertyItemCommands.ResetValue, ExecuteResetValueCommand, CanExecuteResetValueCommand)); + + AddHandler(Mouse.MouseDownEvent, new MouseButtonEventHandler(PropertyItem_MouseDown), true); + AddHandler(Mouse.PreviewMouseDownEvent, new MouseButtonEventHandler(PropertyItem_PreviewMouseDown), true); } #endregion //Constructor - #region Base Class Overrides + #region Event Handlers - protected override void OnMouseLeftButtonDown(System.Windows.Input.MouseButtonEventArgs e) + void PropertyItem_MouseDown(object sender, MouseButtonEventArgs e) { - IsSelected = true; - if (Editor != null) Editor.Focus(); e.Handled = true; } - #endregion //Base Class Overrides + void PropertyItem_PreviewMouseDown(object sender, MouseButtonEventArgs e) + { + IsSelected = true; + + //if it is a comboBox then the selection will not take when Focus is called + if (!(e.Source is ComboBox)) + Focus(); + } + + #endregion //Event Handlers + + #region Commands + + private void ExecuteResetValueCommand(object sender, ExecutedRoutedEventArgs e) + { + if (PropertyDescriptor.CanResetValue(Instance)) + PropertyDescriptor.ResetValue(Instance); + + //TODO: notify UI that the ValueSource may have changed to update the icon + } + + private void CanExecuteResetValueCommand(object sender, CanExecuteRoutedEventArgs e) + { + bool canExecute = false; + + if (PropertyDescriptor.CanResetValue(Instance) && !PropertyDescriptor.IsReadOnly) + { + canExecute = true; + } + + e.CanExecute = canExecute; + } + + #endregion //Commands } } diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Themes/Generic.xaml b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Themes/Generic.xaml index ce62e3c5..59e7645f 100644 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Themes/Generic.xaml +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Themes/Generic.xaml @@ -1,13 +1,18 @@  + xmlns:converters="clr-namespace:Microsoft.Windows.Controls.Core.Converters" + xmlns:pgConverters="clr-namespace:Microsoft.Windows.Controls.PropertyGrid.Converters" + xmlns:utilities="clr-namespace:Microsoft.Windows.Controls.Core.Utilities" + xmlns:commands="clr-namespace:Microsoft.Windows.Controls.PropertyGrid.Commands"> + + @@ -213,12 +218,17 @@