1 namespace System.Activities.Presentation.PropertyEditing
3 using System.Windows.Controls;
6 using System.Windows.Data;
7 using System.Diagnostics;
8 using System.Diagnostics.CodeAnalysis;
9 using System.Windows.Input;
10 using System.Windows.Controls.Primitives;
11 using System.Windows.Media;
12 using System.ComponentModel;
13 using System.Collections.Generic;
14 using System.Activities.Presentation;
16 using System.Activities.Presentation.Internal.PropertyEditing.Editors;
17 using System.Activities.Presentation.Internal.PropertyEditing;
20 /// This control is used as a graphical container for PropertyEntry instances. The control is
21 /// look-less. However, it is generally styled as a horizontal row that includes the
22 /// name of the property followed by an editor for its value. This control, however, is
23 /// intended to be restiled by 3rd-parties to suite their needs. The style is controled
24 /// by three ControlTemplates (InlineRowTemplate, ExtendedPopupRowTemplate, and
25 /// ExtendedPinnedRowTemplate) that are chosed by the logic within this control based
26 /// on the current value of ActiveEditMode. This control also exposes three DataTemplates
27 /// (InlineEditor, ExtendedEditor, and DialogEditor) that each of the row templates can use
28 /// to display the appropriate value editor for the PropertyValue being edited.
30 class PropertyContainer : Control, INotifyPropertyChanged
33 private static RoutedCommand _openDialogWindow;
35 DataTemplate flagEditorTemplate;
38 /// INotifyPropertyChanged event
40 public event PropertyChangedEventHandler PropertyChanged;
42 internal event DependencyPropertyChangedEventHandler DependencyPropertyChanged;
44 private bool _attachedToPropertyEntryEvents;
47 /// Creates a PropertyContainer
49 [SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
50 public PropertyContainer()
53 // Set the OwningPropertyContainer (attached, inherited DP) to self,
54 // so that all of the children of this control know which PropertyContainer
56 SetOwningPropertyContainer(this, this);
58 this.Loaded += new RoutedEventHandler(OnLoaded);
59 this.Unloaded += new RoutedEventHandler(OnUnloaded);
66 public static readonly DependencyProperty IsValueEditEnabledProperty = DependencyProperty.Register(
69 typeof(PropertyContainer),
70 new UIPropertyMetadata(true));
74 /// Gets or sets the PropertyEntry instance on which this PropertyContainer operates.
75 /// That is the context of the PropertyContainer. The exposed editor templates
76 /// (InlineEditor, ExtendedEditor, and DialogEditor) are based on the value of this property.
78 public static readonly DependencyProperty PropertyEntryProperty =
79 DependencyProperty.Register(
81 typeof(PropertyEntry),
82 typeof(PropertyContainer),
83 new FrameworkPropertyMetadata(
85 new PropertyChangedCallback(PropertyEntryPropertyChanged)));
88 /// Gets or sets the PropertyEntry instance on which this PropertyContainer operates.
89 /// That is the context of the PropertyContainer. The exposed editor templates
90 /// (InlineEditor, ExtendedEditor, and DialogEditor) are based on the value of this property.
92 [Fx.Tag.KnownXamlExternalAttribute]
93 public PropertyEntry PropertyEntry
95 get { return (PropertyEntry)this.GetValue(PropertyContainer.PropertyEntryProperty); }
96 set { this.SetValue(PropertyContainer.PropertyEntryProperty, value); }
99 public bool IsValueEditEnabled
101 get { return (bool)GetValue(IsValueEditEnabledProperty); }
102 set { SetValue(IsValueEditEnabledProperty, value); }
105 private static void PropertyEntryPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
107 PropertyContainer theThis = (PropertyContainer)obj;
109 // Since the underlying property has changed, chances are that the inline or extended editors
110 // have changed as well, so fire events indicating that their values have changed
111 theThis.NotifyTemplatesChanged();
112 theThis.OnPropertyChanged("MatchesFilter");
114 // Switch back to Inline mode
115 theThis.ActiveEditMode = PropertyContainerEditMode.Inline;
117 // Ensure that the Template property of this control is set to the right ControlTemplate
118 UpdateControlTemplate(theThis);
120 // Hook into PropertyEntry's changed events
121 if (e.OldValue != null)
122 theThis.DisassociatePropertyEventHandlers((PropertyEntry)e.OldValue);
123 if (e.NewValue != null)
124 theThis.AssociatePropertyEventHandlers((PropertyEntry)e.NewValue);
136 /// Gets or sets currently displayed edit mode of this container (ie. ExtendedPopup,
137 /// ExtendedPinned, Inline or Dialog).
139 public static readonly DependencyProperty ActiveEditModeProperty =
140 DependencyProperty.Register(
142 typeof(PropertyContainerEditMode),
143 typeof(PropertyContainer),
144 new FrameworkPropertyMetadata(
145 PropertyContainerEditMode.Inline,
146 new PropertyChangedCallback(OnActiveEditModePropertyChanged)));
149 /// Gets or sets currently displayed edit mode of this container (ie. ExtendedPopup,
150 /// ExtendedPinned, Inline or Dialog).
152 public PropertyContainerEditMode ActiveEditMode
154 get { return (PropertyContainerEditMode)this.GetValue(PropertyContainer.ActiveEditModeProperty); }
155 set { this.SetValue(PropertyContainer.ActiveEditModeProperty, value); }
158 private static void OnActiveEditModePropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
160 PropertyContainer theThis = (PropertyContainer)obj;
162 // Ensure that the Template property of this control is set to the right ControlTemplate
163 UpdateControlTemplate(theThis);
165 // Invoke a dialog editor if needed
166 if (object.Equals(e.NewValue, PropertyContainerEditMode.Dialog))
169 if (OpenDialogWindow.CanExecute(null, theThis))
171 // There is someone who handles this command, so let it deal with it
173 OpenDialogWindow.Execute(null, theThis);
177 // There is no-one handling this command, so see if there is a virtual
178 // method we can invoke
179 DialogPropertyValueEditor editor = theThis.FindDialogPropertyValueEditor();
182 // If the DialogCommandSource is not explicitly set, use this control as the
184 IInputElement dialogCommandSource = theThis.DialogCommandSource ?? theThis;
185 editor.ShowDialog(theThis.PropertyEntry.PropertyValue, dialogCommandSource);
189 // And revert back to old edit mode once done
190 theThis.ActiveEditMode = (PropertyContainerEditMode)e.OldValue;
195 // DialogCommandSource DP
198 /// Gets or sets the IInputElement to pass into the ShowDialog() method as the command source.
199 /// If null (default), _this_ will be passed in.
200 /// Note: ShowDialog() method is called on a DialogPropertyValueEditor instance if a dialog editor
201 /// is invoked and the editor does not specify any dialog DataTemplate.
203 public static readonly DependencyProperty DialogCommandSourceProperty =
204 DependencyProperty.Register(
205 "DialogCommandSource",
206 typeof(IInputElement),
207 typeof(PropertyContainer),
208 new PropertyMetadata((IInputElement)null));
211 /// Gets or sets the IInputElement to pass into the ShowDialog() method as the command source.
212 /// If null (default), _this_ will be passed in.
213 /// Note: ShowDialog() method is called on a DialogPropertyValueEditor instance if a dialog editor
214 /// is invoked and the editor does not specify any dialog DataTemplate.
216 [Fx.Tag.KnownXamlExternalAttribute]
217 public IInputElement DialogCommandSource
219 get { return (IInputElement)this.GetValue(DialogCommandSourceProperty); }
220 set { this.SetValue(DialogCommandSourceProperty, value); }
224 // OwningPropertyContainer Attached, Inherited DP
227 /// Attached, inherited DP that can be used by UI elements of PropertyValueEditors
228 /// to gain access to their parent PropertyContainer.
230 public static readonly DependencyProperty OwningPropertyContainerProperty =
231 DependencyProperty.RegisterAttached(
232 "OwningPropertyContainer",
233 typeof(PropertyContainer),
234 typeof(PropertyContainer),
235 new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.Inherits));
238 /// Setter for attached, inherited DP that can be used by UI elements of PropertyValueEditors
239 /// to gain access to their parent PropertyContainer.
241 /// <param name="dependencyObject">The DO to set the property on</param>
242 /// <param name="value">The Owning PropertyContainer</param>
243 public static void SetOwningPropertyContainer(DependencyObject dependencyObject, PropertyContainer value)
245 if (dependencyObject == null)
246 throw FxTrace.Exception.ArgumentNull("dependencyObject");
248 dependencyObject.SetValue(PropertyContainer.OwningPropertyContainerProperty, value);
252 /// Getter for attached, inherited DP that can be used by UI elements of PropertyValueEditors
253 /// to gain access to their parent PropertyContainer.
255 /// <param name="dependencyObject">The DO to get the property from</param>
256 /// <returns>The owning PropertyContainer</returns>
257 public static PropertyContainer GetOwningPropertyContainer(DependencyObject dependencyObject)
259 if (dependencyObject == null)
260 throw FxTrace.Exception.ArgumentNull("dependencyObject");
262 return (PropertyContainer)dependencyObject.GetValue(PropertyContainer.OwningPropertyContainerProperty);
266 // ControlTemplates for PropertyContainer to define the UI for the different edit modes
268 // InlineRowTemplate DP
271 /// This DP is used to get/set the InlineRowTemplate for the PropertyContainer. The
272 /// InlineRowTemplate defines how the PropertyContainer renders itself when
273 /// ActiveEditMode = Inline.
275 public static readonly DependencyProperty InlineRowTemplateProperty =
276 DependencyProperty.Register(
278 typeof(ControlTemplate),
279 typeof(PropertyContainer),
280 new FrameworkPropertyMetadata(
282 FrameworkPropertyMetadataOptions.None,
283 new PropertyChangedCallback(RowTemplateChanged)));
286 /// Gets or sets the InlineRowTemplate for the PropertyContainer. The
287 /// InlineRowTemplate defines how the PropertyContainer renders itself when
288 /// ActiveEditMode = Inline.
290 [Fx.Tag.KnownXamlExternalAttribute]
291 public ControlTemplate InlineRowTemplate
293 get { return (ControlTemplate)this.GetValue(PropertyContainer.InlineRowTemplateProperty); }
294 set { this.SetValue(PropertyContainer.InlineRowTemplateProperty, value); }
297 // Called when any of the row templates (InlineRowTemplate, ExtendedPopupRowTemplate, ExtendedPinnedRowTemplate)
299 private static void RowTemplateChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
301 PropertyContainer theThis = (PropertyContainer)obj;
302 bool updateControlTemplate = false;
304 // Check InlineRowTemplate
305 updateControlTemplate = updateControlTemplate |
306 (e.Property == PropertyContainer.InlineRowTemplateProperty &&
307 theThis.ActiveEditMode == PropertyContainerEditMode.Inline);
309 // Check ExtendedPopup
310 updateControlTemplate = updateControlTemplate |
311 (e.Property == PropertyContainer.ExtendedPopupRowTemplateProperty &&
312 theThis.ActiveEditMode == PropertyContainerEditMode.ExtendedPopup);
314 // Check ExtendedPinned
315 updateControlTemplate = updateControlTemplate |
316 (e.Property == PropertyContainer.ExtendedPinnedRowTemplateProperty &&
317 theThis.ActiveEditMode == PropertyContainerEditMode.ExtendedPinned);
319 if (updateControlTemplate)
320 UpdateControlTemplate(theThis);
324 // ExtendedPopupRowTemplate DP
327 /// This DP is used to get/set the ExtendedPopupRowTemplate for this PropertyContainer.
328 /// The ExtendedPopupRowTemplate defines how the PropertyContainer renders itself when
329 /// ActiveEditMode = ExtendedPopup. Generally, host implementations will define this
330 /// template to automatically include the InlineRowTemplate as well.
332 public static readonly DependencyProperty ExtendedPopupRowTemplateProperty =
333 DependencyProperty.Register(
334 "ExtendedPopupRowTemplate",
335 typeof(ControlTemplate),
336 typeof(PropertyContainer),
337 new FrameworkPropertyMetadata(
339 FrameworkPropertyMetadataOptions.None,
340 new PropertyChangedCallback(RowTemplateChanged)));
343 /// Gets or sets the ExtendedPopupRowTemplate for this PropertyContainer.
344 /// The ExtendedPopupRowTemplate defines how the PropertyContainer renders itself when
345 /// ActiveEditMode = ExtendedPopup. Generally, host implementations will define this
346 /// template to automatically include the InlineRowTemplate as well.
348 [Fx.Tag.KnownXamlExternalAttribute]
349 public ControlTemplate ExtendedPopupRowTemplate
351 get { return (ControlTemplate)this.GetValue(PropertyContainer.ExtendedPopupRowTemplateProperty); }
352 set { this.SetValue(PropertyContainer.ExtendedPopupRowTemplateProperty, value); }
356 // ExtendedPinnedRowTemplate DP
359 /// This DP is used to get/set the ExtendedPinnedRowTemplate for this PropertyContainer.
360 /// The ExtendedPinnedRowTemplate defines how the PropertyContainer renders itself when
361 /// ActiveEditMode = ExtendedPinned. Generally, host implementations will define this
362 /// template to automatically include the InlineRowTemplate as well.
364 public static readonly DependencyProperty ExtendedPinnedRowTemplateProperty =
365 DependencyProperty.Register(
366 "ExtendedPinnedRowTemplate",
367 typeof(ControlTemplate),
368 typeof(PropertyContainer),
369 new FrameworkPropertyMetadata(
371 FrameworkPropertyMetadataOptions.None,
372 new PropertyChangedCallback(RowTemplateChanged)));
375 /// Get/set the ExtendedPinnedRowTemplate for this PropertyContainer.
376 /// The ExtendedPinnedRowTemplate defines how the PropertyContainer renders itself when
377 /// ActiveEditMode = ExtendedPinned. Generally, host implementations will define this
378 /// template to automatically include the InlineRowTemplate as well.
380 [Fx.Tag.KnownXamlExternalAttribute]
381 public ControlTemplate ExtendedPinnedRowTemplate
383 get { return (ControlTemplate)this.GetValue(PropertyContainer.ExtendedPinnedRowTemplateProperty); }
384 set { this.SetValue(PropertyContainer.ExtendedPinnedRowTemplateProperty, value); }
388 // Default PropertyValueEditors to use when a given property doesn't specify its own
390 // DefaultStandardValuesPropertyValueEditor DP
393 /// DP to get or set the default standard-values editor which is used when a PropertyEntry supports
394 /// StandardValues (enum or through a TypeConverter) and there isn't a PropertyValueEditor
395 /// defined for the PropertyEntry or Type explicitely.
397 public static readonly DependencyProperty DefaultStandardValuesPropertyValueEditorProperty =
398 DependencyProperty.Register(
399 "DefaultStandardValuesPropertyValueEditor",
400 typeof(PropertyValueEditor),
401 typeof(PropertyContainer),
402 new FrameworkPropertyMetadata(
404 new PropertyChangedCallback(DefaultPropertyValueEditorChanged)));
407 /// Gets or set the default standard-values editor which is used when a PropertyEntry supports
408 /// StandardValues (enum or through a TypeConverter) and there isn't a PropertyValueEditor
409 /// defined for the PropertyEntry or Type explicitely.
411 [Fx.Tag.KnownXamlExternalAttribute]
412 public PropertyValueEditor DefaultStandardValuesPropertyValueEditor
414 get { return (PropertyValueEditor)this.GetValue(PropertyContainer.DefaultStandardValuesPropertyValueEditorProperty); }
415 set { this.SetValue(PropertyContainer.DefaultStandardValuesPropertyValueEditorProperty, value); }
418 private static void DefaultPropertyValueEditorChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
420 PropertyContainer theThis = (PropertyContainer)obj;
422 // Since one of the default PVE's has changed, chances are that the Inline or the Extended
423 // editor template has changed as well.
424 theThis.NotifyTemplatesChanged();
428 // DefaultPropertyValueEditor DP
431 /// DP to get or set the default PropertyValueEditor which is the editor used when the
432 /// PropertyEntry or Type does not explicitely define its own PropertyValueEditor and does not
433 /// support StandardValues.
435 public static readonly DependencyProperty DefaultPropertyValueEditorProperty =
436 DependencyProperty.Register(
437 "DefaultPropertyValueEditor",
438 typeof(PropertyValueEditor),
439 typeof(PropertyContainer),
440 new FrameworkPropertyMetadata(
442 new PropertyChangedCallback(DefaultPropertyValueEditorChanged)));
445 /// Gets or sets the default PropertyValueEditor which is the editor used when the
446 /// PropertyEntry or Type does not explicitely define its own PropertyValueEditor and does not
447 /// support StandardValues.
449 [Fx.Tag.KnownXamlExternalAttribute]
450 public PropertyValueEditor DefaultPropertyValueEditor
452 get { return (PropertyValueEditor)this.GetValue(PropertyContainer.DefaultPropertyValueEditorProperty); }
453 set { this.SetValue(PropertyContainer.DefaultPropertyValueEditorProperty, value); }
457 // Regular properties (read-only values for DataBinding)
459 // InlineEditorTemplate read-only CLR property
462 /// Gets the most appropriate InlineEditorTemplate for the current PropertyEntry.
463 /// A row template may decide to use this value to render the editor on the appropriate place.
465 [Fx.Tag.KnownXamlExternalAttribute]
466 public DataTemplate InlineEditorTemplate
470 return FindPropertyValueEditorTemplate(PropertyContainerEditMode.Inline);
475 // ExtendedEditorTemplate read-only CLR property
478 /// Gets the most appropriate ExtendedEditorTemplate for the current PropertyEntry.
479 /// A row template may decide to use this value to render the editor on the appropriate place.
481 [Fx.Tag.KnownXamlExternalAttribute]
482 public DataTemplate ExtendedEditorTemplate
486 return FindPropertyValueEditorTemplate(PropertyContainerEditMode.ExtendedPinned);
491 // DialogEditorTemplate read-only CLR property
494 /// Gets the most appropriate DialogEditorTemplate for the current PropertyEntry.
495 /// A row template or a Dialog may decide to use this value to render the editor on the
496 /// appropriate place.
498 [Fx.Tag.KnownXamlExternalAttribute]
499 public DataTemplate DialogEditorTemplate
503 return FindPropertyValueEditorTemplate(PropertyContainerEditMode.Dialog);
508 // MatchesFilter read-only CLR property
511 /// Gets the value for MatchesFilter stored in the contained PropertyEntry. If the PropertyEntry
512 /// is null, the value returned is false.
513 /// This property can be used to trigger UI changes to the PropertyContainer based on
514 /// whether the current PropertyEntry matches the current filter or not.
516 public bool MatchesFilter
520 PropertyEntry property = this.PropertyEntry;
521 return property != null && property.MatchesFilter;
526 // OpenDialogWindow static, read-only command property
529 /// Gets the command that is fired when someone changes the ActiveEditMode property to "Dialog".
530 /// The host may choose to handle this command and, display the DialogEditorTemplate
531 /// (if one exists) in a host-specific dialog container. If the host does not handle
532 /// this command (OpenDialogWindow.CanExecute is false), the PropertyContainer itself
533 /// defaults to calling into the virtual DialogPropertyValueEditor.ShowDialog()
534 /// method, but only if DialogPropertyValueEditor is found.
536 public static RoutedCommand OpenDialogWindow
540 if (_openDialogWindow == null)
541 _openDialogWindow = new RoutedCommand("OpenDialogWindow", typeof(PropertyContainer));
543 return _openDialogWindow;
548 internal bool SupportsEditMode(PropertyContainerEditMode mode)
550 // special handling for dialog editor
551 if (mode == PropertyContainerEditMode.Dialog)
552 return FindDialogPropertyValueEditor() != null;
554 // for everything else
555 return FindPropertyValueEditorTemplate(mode) != null;
558 // When the control gets unloaded, unhook any remaining event handlers
559 // so that it can be garbage collected
560 private void OnUnloaded(object sender, RoutedEventArgs e)
562 PropertyEntry entry = this.PropertyEntry;
564 DisassociatePropertyEventHandlers(entry);
567 // When the control gets re-loaded, re-hook any previous event handlers
568 // that may have been disassociated during Unload
569 private void OnLoaded(object sender, RoutedEventArgs e)
571 PropertyEntry entry = this.PropertyEntry;
573 AssociatePropertyEventHandlers(entry);
576 // Helper that hooks into PropertyChanged events on the given Property
577 private void AssociatePropertyEventHandlers(PropertyEntry property)
579 if (!_attachedToPropertyEntryEvents)
581 property.PropertyChanged += new PropertyChangedEventHandler(OnPropertyPropertyChanged);
582 _attachedToPropertyEntryEvents = true;
586 // Helper that unhooks from PropertyChanged events on the given Property
587 private void DisassociatePropertyEventHandlers(PropertyEntry property)
589 if (_attachedToPropertyEntryEvents)
591 property.PropertyChanged -= new PropertyChangedEventHandler(OnPropertyPropertyChanged);
592 _attachedToPropertyEntryEvents = false;
596 // Called when the properties of the Property object change
597 private void OnPropertyPropertyChanged(object sender, PropertyChangedEventArgs e)
599 // Propagate MatchesFilter change notifications outwards so that
600 // people can set up triggers against it
601 if ("MatchesFilter".Equals(e.PropertyName))
602 this.OnPropertyChanged("MatchesFilter");
603 else if ("PropertyValueEditor".Equals(e.PropertyName))
604 this.NotifyTemplatesChanged();
608 /// Helper class that attempts to find the DataTemplate for the requested PropertyContainerEditMode
609 /// given the currently displayed PropertyEntry and the currently set default PropertyValueEditors.
611 /// If the requested DataTemplate is found on the PropertyValueEditor associated with the displayed
612 /// control, is it returned.
614 /// Otherwise if the requested DataTemplate is found on DefaultStandardValuesPropertyValueEditor,
617 /// Otherwise if the requested DataTemplate is found on DefaultPropertyValueEditor,
620 /// Otherwise null is returned.
622 /// <param name="editMode">The editMode for which the DataTemplate should be retrieved</param>
623 /// <returns>Most relevant DataTemplate for the specified edit mode based on the currently
624 /// displayed PropertyEntry and the current set of default PropertyValueEditors, or null if not
626 private DataTemplate FindPropertyValueEditorTemplate(PropertyContainerEditMode editMode)
628 PropertyEntry property = this.PropertyEntry;
629 PropertyValueEditor editor = null;
630 DataTemplate requestedTemplate = null;
633 if (property != null)
635 editor = property.PropertyValueEditor;
638 requestedTemplate = editor.GetPropertyValueEditor(editMode);
642 if (requestedTemplate != null)
643 return requestedTemplate;
645 // Is the property of type enum and used as flags?
646 if (IsFlagsProperty(property))
648 requestedTemplate = this.GetFlagEditorTemplate(editMode);
651 if (requestedTemplate != null)
653 return requestedTemplate;
656 // Does the property have standard values?
657 if (property != null && property.HasStandardValuesInternal)
659 editor = this.DefaultStandardValuesPropertyValueEditor;
662 requestedTemplate = editor.GetPropertyValueEditor(editMode);
666 if (requestedTemplate != null)
667 return requestedTemplate;
670 editor = this.DefaultPropertyValueEditor;
673 requestedTemplate = editor.GetPropertyValueEditor(editMode);
676 return requestedTemplate;
679 bool IsFlagsProperty(PropertyEntry property)
681 return property != null && property.PropertyType != null && property.PropertyType.IsEnum &&
682 ExtensibilityAccessor.GetAttribute<FlagsAttribute>(property.PropertyType) != null;
685 DataTemplate GetFlagEditorTemplate(PropertyContainerEditMode editMode)
687 Type propertyType = this.PropertyEntry.PropertyType;
688 if (editMode == PropertyContainerEditMode.Inline)
690 if (this.flagEditorTemplate == null)
692 this.flagEditorTemplate = new DataTemplate();
693 this.flagEditorTemplate.VisualTree = new FrameworkElementFactory(typeof(FlagEditor));
694 this.flagEditorTemplate.VisualTree.SetValue(FlagEditor.FlagTypeProperty, propertyType);
695 Binding binding = new Binding("Value");
696 binding.Converter = new FlagStringConverter();
697 binding.ConverterParameter = propertyType;
698 binding.UpdateSourceTrigger = UpdateSourceTrigger.Explicit;
699 this.flagEditorTemplate.VisualTree.SetBinding(FlagEditor.TextProperty, binding);
701 return this.flagEditorTemplate;
709 // Helper that tries to find the first applicable DialogPropertyValueEditor
710 private DialogPropertyValueEditor FindDialogPropertyValueEditor()
712 PropertyEntry property = this.PropertyEntry;
713 DialogPropertyValueEditor editor = null;
716 if (property != null)
718 editor = property.PropertyValueEditor as DialogPropertyValueEditor;
724 // Does the property have standard values?
725 if (property != null && property.HasStandardValuesInternal)
727 editor = this.DefaultStandardValuesPropertyValueEditor as DialogPropertyValueEditor;
734 editor = this.DefaultPropertyValueEditor as DialogPropertyValueEditor;
739 // Updates the ControlTemplate of this control based on the currently ActiveEditMode
740 private static void UpdateControlTemplate(PropertyContainer container)
743 PropertyContainerEditMode editMode = container.ActiveEditMode;
744 ControlTemplate newTemplate = null;
748 case PropertyContainerEditMode.Inline:
749 newTemplate = container.InlineRowTemplate;
751 case PropertyContainerEditMode.ExtendedPopup:
752 newTemplate = container.ExtendedPopupRowTemplate;
754 case PropertyContainerEditMode.ExtendedPinned:
755 newTemplate = container.ExtendedPinnedRowTemplate;
757 case PropertyContainerEditMode.Dialog:
758 // In dialog case, just keep the same value
763 System.Globalization.CultureInfo.CurrentCulture,
764 "PropertyContainerEditMode does not yet support PropertyContainerEditMode '{0}'.",
765 editMode.ToString()));
766 newTemplate = container.Template;
770 if (newTemplate != container.Template)
771 container.Template = newTemplate;
774 private void NotifyTemplatesChanged()
776 OnPropertyChanged("InlineEditorTemplate");
777 OnPropertyChanged("ExtendedEditorTemplate");
778 OnPropertyChanged("DialogEditorTemplate");
782 /// Called when a property changes
784 /// <param name="propertyName">Name of the property</param>
785 protected virtual void OnPropertyChanged(string propertyName)
787 if (PropertyChanged != null)
788 PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
792 /// Called when a property changes
794 /// <param name="e">Name of the property</param>
795 protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
797 if (DependencyPropertyChanged != null)
798 DependencyPropertyChanged(this, e);
800 base.OnPropertyChanged(e);