PageRenderTime 36ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/WPFToolkit.Extended/PropertyGrid/Implementation/PropertyItem.cs

#
C# | 415 lines | 308 code | 97 blank | 10 comment | 41 complexity | 5ec6d52da37460c9ea13941c9059a811 MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Linq;
  5. using System.Windows;
  6. using System.Windows.Controls;
  7. using System.Windows.Data;
  8. using System.Windows.Input;
  9. using System.Windows.Markup.Primitives;
  10. using Microsoft.Windows.Controls.PropertyGrid.Commands;
  11. using Microsoft.Windows.Controls.PropertyGrid.Attributes;
  12. namespace Microsoft.Windows.Controls.PropertyGrid
  13. {
  14. public class PropertyItem : Control
  15. {
  16. #region Members
  17. private DependencyPropertyDescriptor _dpDescriptor;
  18. private MarkupObject _markupObject;
  19. #endregion //Members
  20. #region Properties
  21. public string BindingPath { get; private set; }
  22. #region Category
  23. public static readonly DependencyProperty CategoryProperty = DependencyProperty.Register("Category", typeof(string), typeof(PropertyItem), new UIPropertyMetadata(string.Empty));
  24. public string Category
  25. {
  26. get { return (string)GetValue(CategoryProperty); }
  27. set { SetValue(CategoryProperty, value); }
  28. }
  29. #endregion //Category
  30. #region Description
  31. public string Description
  32. {
  33. get { return PropertyDescriptor.Description; }
  34. }
  35. #endregion //Description
  36. #region DisplayName
  37. public static readonly DependencyProperty DisplayNameProperty = DependencyProperty.Register("DisplayName", typeof(string), typeof(PropertyItem), new UIPropertyMetadata(null));
  38. public string DisplayName
  39. {
  40. get { return (string)GetValue(DisplayNameProperty); }
  41. set { SetValue(DisplayNameProperty, value); }
  42. }
  43. #endregion //DisplayName
  44. #region Editor
  45. public static readonly DependencyProperty EditorProperty = DependencyProperty.Register("Editor", typeof(FrameworkElement), typeof(PropertyItem), new UIPropertyMetadata(null, OnEditorChanged));
  46. public FrameworkElement Editor
  47. {
  48. get { return (FrameworkElement)GetValue(EditorProperty); }
  49. set { SetValue(EditorProperty, value); }
  50. }
  51. private static void OnEditorChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
  52. {
  53. PropertyItem propertyItem = o as PropertyItem;
  54. if (propertyItem != null)
  55. propertyItem.OnEditorChanged((FrameworkElement)e.OldValue, (FrameworkElement)e.NewValue);
  56. }
  57. protected virtual void OnEditorChanged(FrameworkElement oldValue, FrameworkElement newValue)
  58. {
  59. if (oldValue != null)
  60. oldValue.DataContext = null;
  61. if (newValue != null)
  62. newValue.DataContext = this;
  63. }
  64. #endregion //Editor
  65. #region Instance
  66. private object _instance;
  67. public object Instance
  68. {
  69. get { return _instance; }
  70. private set
  71. {
  72. _instance = value;
  73. _markupObject = MarkupWriter.GetMarkupObjectFor(_instance);
  74. }
  75. }
  76. #endregion //Instance
  77. #region IsDataBound
  78. /// <summary>
  79. /// Gets if the property is data bound
  80. /// </summary>
  81. public bool IsDataBound
  82. {
  83. get
  84. {
  85. var dependencyObject = Instance as DependencyObject;
  86. if (dependencyObject != null && _dpDescriptor != null)
  87. return BindingOperations.GetBindingExpressionBase(dependencyObject, _dpDescriptor.DependencyProperty) != null;
  88. return false;
  89. }
  90. }
  91. #endregion //IsDataBound
  92. #region IsDynamicResource
  93. public bool IsDynamicResource
  94. {
  95. get
  96. {
  97. var markupProperty = _markupObject.Properties.Where(p => p.Name == PropertyDescriptor.Name).FirstOrDefault();
  98. if (markupProperty != null)
  99. return markupProperty.Value is DynamicResourceExtension;
  100. return false;
  101. }
  102. }
  103. #endregion //IsDynamicResource
  104. #region IsExpanded
  105. public static readonly DependencyProperty IsExpandedProperty = DependencyProperty.Register("IsExpanded", typeof(bool), typeof(PropertyItem), new UIPropertyMetadata(false, OnIsExpandedChanged));
  106. public bool IsExpanded
  107. {
  108. get { return (bool)GetValue(IsExpandedProperty); }
  109. set { SetValue(IsExpandedProperty, value); }
  110. }
  111. private static void OnIsExpandedChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
  112. {
  113. PropertyItem propertyItem = o as PropertyItem;
  114. if (propertyItem != null)
  115. propertyItem.OnIsExpandedChanged((bool)e.OldValue, (bool)e.NewValue);
  116. }
  117. protected virtual void OnIsExpandedChanged(bool oldValue, bool newValue)
  118. {
  119. if (newValue && (Properties == null || Properties.Count == 0))
  120. {
  121. GetChildProperties();
  122. }
  123. }
  124. #endregion IsExpanded
  125. #region HasChildProperties
  126. public static readonly DependencyProperty HasChildPropertiesProperty = DependencyProperty.Register("HasChildProperties", typeof(bool), typeof(PropertyItem), new UIPropertyMetadata(false));
  127. public bool HasChildProperties
  128. {
  129. get { return (bool)GetValue(HasChildPropertiesProperty); }
  130. set { SetValue(HasChildPropertiesProperty, value); }
  131. }
  132. #endregion HasChildProperties
  133. #region HasResourceApplied
  134. public bool HasResourceApplied
  135. {
  136. //TODO: need to find a better way to determine if a StaticResource has been applied to any property not just a style
  137. get
  138. {
  139. var markupProperty = _markupObject.Properties.Where(p => p.Name == PropertyDescriptor.Name).FirstOrDefault();
  140. if (markupProperty != null)
  141. return markupProperty.Value is Style;
  142. return false;
  143. }
  144. }
  145. #endregion //HasResourceApplied
  146. public bool IsReadOnly { get; private set; }
  147. #region IsSelected
  148. public static readonly DependencyProperty IsSelectedProperty = DependencyProperty.Register("IsSelected", typeof(bool), typeof(PropertyItem), new UIPropertyMetadata(false, OnIsSelectedChanged));
  149. public bool IsSelected
  150. {
  151. get { return (bool)GetValue(IsSelectedProperty); }
  152. set { SetValue(IsSelectedProperty, value); }
  153. }
  154. private static void OnIsSelectedChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
  155. {
  156. PropertyItem propertyItem = o as PropertyItem;
  157. if (propertyItem != null)
  158. propertyItem.OnIsSelectedChanged((bool)e.OldValue, (bool)e.NewValue);
  159. }
  160. protected virtual void OnIsSelectedChanged(bool oldValue, bool newValue)
  161. {
  162. if (newValue)
  163. PropertyGrid.SelectedProperty = this;
  164. }
  165. #endregion //IsSelected
  166. #region Level
  167. public static readonly DependencyProperty LevelProperty = DependencyProperty.Register("Level", typeof(int), typeof(PropertyItem), new UIPropertyMetadata(0));
  168. public int Level
  169. {
  170. get { return (int)GetValue(LevelProperty); }
  171. set { SetValue(LevelProperty, value); }
  172. }
  173. #endregion //Level
  174. #region Properties
  175. public static readonly DependencyProperty PropertiesProperty = DependencyProperty.Register("Properties", typeof(PropertyItemCollection), typeof(PropertyItem), new UIPropertyMetadata(null));
  176. public PropertyItemCollection Properties
  177. {
  178. get { return (PropertyItemCollection)GetValue(PropertiesProperty); }
  179. set { SetValue(PropertiesProperty, value); }
  180. }
  181. #endregion //Properties
  182. #region PropertyDescriptor
  183. private PropertyDescriptor _propertyDescriptor;
  184. public PropertyDescriptor PropertyDescriptor
  185. {
  186. get
  187. {
  188. return _propertyDescriptor;
  189. }
  190. private set
  191. {
  192. _propertyDescriptor = value;
  193. _dpDescriptor = DependencyPropertyDescriptor.FromProperty(_propertyDescriptor);
  194. }
  195. }
  196. #endregion //PropertyDescriptor
  197. public PropertyGrid PropertyGrid { get; private set; }
  198. #region PropertyType
  199. public Type PropertyType
  200. {
  201. get { return PropertyDescriptor.PropertyType; }
  202. }
  203. #endregion //PropertyType
  204. public ICommand ResetValueCommand { get; private set; }
  205. #region Value
  206. public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(object), typeof(PropertyItem), new UIPropertyMetadata(null, OnValueChanged));
  207. public object Value
  208. {
  209. get { return (object)GetValue(ValueProperty); }
  210. set { SetValue(ValueProperty, value); }
  211. }
  212. private static void OnValueChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
  213. {
  214. PropertyItem propertyItem = o as PropertyItem;
  215. if (propertyItem != null)
  216. propertyItem.OnValueChanged((object)e.OldValue, (object)e.NewValue);
  217. }
  218. protected virtual void OnValueChanged(object oldValue, object newValue)
  219. {
  220. // TODO: Add your property changed side-effects. Descendants can override as well.
  221. }
  222. #endregion //Value
  223. #region ValueSource
  224. /// <summary>
  225. /// Gets the value source.
  226. /// </summary>
  227. public BaseValueSource ValueSource
  228. {
  229. get
  230. {
  231. var dependencyObject = Instance as DependencyObject;
  232. if (_dpDescriptor != null && dependencyObject != null)
  233. return DependencyPropertyHelper.GetValueSource(dependencyObject, _dpDescriptor.DependencyProperty).BaseValueSource;
  234. return BaseValueSource.Unknown;
  235. }
  236. }
  237. #endregion //ValueSource
  238. #endregion //Properties
  239. #region Constructors
  240. static PropertyItem()
  241. {
  242. DefaultStyleKeyProperty.OverrideMetadata(typeof(PropertyItem), new FrameworkPropertyMetadata(typeof(PropertyItem)));
  243. }
  244. public PropertyItem(object instance, PropertyDescriptor property, PropertyGrid propertyGrid, string bindingPath)
  245. {
  246. PropertyDescriptor = property;
  247. PropertyGrid = propertyGrid;
  248. Instance = instance;
  249. BindingPath = bindingPath;
  250. SetPropertyDescriptorProperties();
  251. ResolveExpandableObject();
  252. CommandBindings.Add(new CommandBinding(PropertyItemCommands.ResetValue, ExecuteResetValueCommand, CanExecuteResetValueCommand));
  253. AddHandler(Mouse.PreviewMouseDownEvent, new MouseButtonEventHandler(PropertyItem_PreviewMouseDown), true);
  254. }
  255. #endregion //Constructors
  256. #region Event Handlers
  257. void PropertyItem_PreviewMouseDown(object sender, MouseButtonEventArgs e)
  258. {
  259. IsSelected = true;
  260. }
  261. #endregion //Event Handlers
  262. #region Commands
  263. private void ExecuteResetValueCommand(object sender, ExecutedRoutedEventArgs e)
  264. {
  265. if (PropertyDescriptor.CanResetValue(Instance))
  266. PropertyDescriptor.ResetValue(Instance);
  267. //TODO: notify UI that the ValueSource may have changed to update the icon
  268. }
  269. private void CanExecuteResetValueCommand(object sender, CanExecuteRoutedEventArgs e)
  270. {
  271. bool canExecute = false;
  272. if (PropertyDescriptor.CanResetValue(Instance) && !PropertyDescriptor.IsReadOnly)
  273. {
  274. canExecute = true;
  275. }
  276. e.CanExecute = canExecute;
  277. }
  278. #endregion //Commands
  279. #region Methods
  280. private void GetChildProperties()
  281. {
  282. if (Value == null)
  283. return;
  284. var propertyItems = new List<PropertyItem>();
  285. try
  286. {
  287. PropertyDescriptorCollection descriptors = PropertyGridUtilities.GetPropertyDescriptors(Value);
  288. foreach (PropertyDescriptor descriptor in descriptors)
  289. {
  290. if (descriptor.IsBrowsable)
  291. propertyItems.Add(PropertyGridUtilities.CreatePropertyItem(descriptor, Instance, PropertyGrid, String.Format("{0}.{1}", BindingPath, descriptor.Name), Level + 1));
  292. }
  293. }
  294. catch (Exception ex)
  295. {
  296. //TODO: handle this some how
  297. }
  298. Properties = PropertyGridUtilities.GetAlphabetizedProperties(propertyItems);
  299. }
  300. private void ResolveExpandableObject()
  301. {
  302. var attribute = PropertyGridUtilities.GetAttribute<ExpandableObjectAttribute>(PropertyDescriptor);
  303. if (attribute != null)
  304. {
  305. HasChildProperties = true;
  306. IsReadOnly = true;
  307. }
  308. }
  309. private void SetPropertyDescriptorProperties()
  310. {
  311. Name = PropertyDescriptor.Name;
  312. DisplayName = PropertyDescriptor.DisplayName;
  313. Category = PropertyDescriptor.Category;
  314. IsReadOnly = PropertyDescriptor.IsReadOnly;
  315. }
  316. #endregion //Methods
  317. }
  318. }