Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / NetFx40 / Tools / System.Activities.Presentation / System / Activities / Presentation / Base / Core / PropertyEditing / PropertyContainer.cs / 1305376 / PropertyContainer.cs
namespace System.Activities.Presentation.PropertyEditing {
using System.Windows.Controls;
using System.Windows;
using System;
using System.Windows.Data;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Windows.Input;
using System.Windows.Controls.Primitives;
using System.Windows.Media;
using System.ComponentModel;
using System.Collections.Generic;
using System.Activities.Presentation;
using System.Runtime;
using System.Activities.Presentation.Internal.PropertyEditing.Editors;
using System.Activities.Presentation.Internal.PropertyEditing;
///
/// This control is used as a graphical container for PropertyEntry instances. The control is
/// look-less. However, it is generally styled as a horizontal row that includes the
/// name of the property followed by an editor for its value. This control, however, is
/// intended to be restiled by 3rd-parties to suite their needs. The style is controled
/// by three ControlTemplates (InlineRowTemplate, ExtendedPopupRowTemplate, and
/// ExtendedPinnedRowTemplate) that are chosed by the logic within this control based
/// on the current value of ActiveEditMode. This control also exposes three DataTemplates
/// (InlineEditor, ExtendedEditor, and DialogEditor) that each of the row templates can use
/// to display the appropriate value editor for the PropertyValue being edited.
///
class PropertyContainer : Control, INotifyPropertyChanged {
private static RoutedCommand _openDialogWindow;
DataTemplate flagEditorTemplate;
///
/// INotifyPropertyChanged event
///
public event PropertyChangedEventHandler PropertyChanged;
internal event DependencyPropertyChangedEventHandler DependencyPropertyChanged;
private bool _attachedToPropertyEntryEvents;
///
/// Creates a PropertyContainer
///
[SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public PropertyContainer() {
// Set the OwningPropertyContainer (attached, inherited DP) to self,
// so that all of the children of this control know which PropertyContainer
// they belong to
SetOwningPropertyContainer(this, this);
this.Loaded += new RoutedEventHandler(OnLoaded);
this.Unloaded += new RoutedEventHandler(OnUnloaded);
}
// Useful DPs
// PropertyEntry DP
public static readonly DependencyProperty IsValueEditEnabledProperty = DependencyProperty.Register(
"IsValueEditEnabled",
typeof(bool),
typeof(PropertyContainer),
new UIPropertyMetadata(true));
///
/// Gets or sets the PropertyEntry instance on which this PropertyContainer operates.
/// That is the context of the PropertyContainer. The exposed editor templates
/// (InlineEditor, ExtendedEditor, and DialogEditor) are based on the value of this property.
///
public static readonly DependencyProperty PropertyEntryProperty =
DependencyProperty.Register(
"PropertyEntry",
typeof(PropertyEntry),
typeof(PropertyContainer),
new FrameworkPropertyMetadata(
null,
new PropertyChangedCallback(PropertyEntryPropertyChanged)));
///
/// Gets or sets the PropertyEntry instance on which this PropertyContainer operates.
/// That is the context of the PropertyContainer. The exposed editor templates
/// (InlineEditor, ExtendedEditor, and DialogEditor) are based on the value of this property.
///
[Fx.Tag.KnownXamlExternalAttribute]
public PropertyEntry PropertyEntry
{
get { return (PropertyEntry)this.GetValue(PropertyContainer.PropertyEntryProperty); }
set { this.SetValue(PropertyContainer.PropertyEntryProperty, value); }
}
public bool IsValueEditEnabled
{
get { return (bool)GetValue(IsValueEditEnabledProperty); }
set { SetValue(IsValueEditEnabledProperty, value); }
}
private static void PropertyEntryPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) {
PropertyContainer theThis = (PropertyContainer)obj;
// Since the underlying property has changed, chances are that the inline or extended editors
// have changed as well, so fire events indicating that their values have changed
theThis.NotifyTemplatesChanged();
theThis.OnPropertyChanged("MatchesFilter");
// Switch back to Inline mode
theThis.ActiveEditMode = PropertyContainerEditMode.Inline;
// Ensure that the Template property of this control is set to the right ControlTemplate
UpdateControlTemplate(theThis);
// Hook into PropertyEntry's changed events
if (e.OldValue != null)
theThis.DisassociatePropertyEventHandlers((PropertyEntry)e.OldValue);
if (e.NewValue != null)
theThis.AssociatePropertyEventHandlers((PropertyEntry)e.NewValue);
}
// ActiveEditMode DP
//
///
/// Gets or sets currently displayed edit mode of this container (ie. ExtendedPopup,
/// ExtendedPinned, Inline or Dialog).
///
public static readonly DependencyProperty ActiveEditModeProperty =
DependencyProperty.Register(
"ActiveEditMode",
typeof(PropertyContainerEditMode),
typeof(PropertyContainer),
new FrameworkPropertyMetadata(
PropertyContainerEditMode.Inline,
new PropertyChangedCallback(OnActiveEditModePropertyChanged)));
///
/// Gets or sets currently displayed edit mode of this container (ie. ExtendedPopup,
/// ExtendedPinned, Inline or Dialog).
///
public PropertyContainerEditMode ActiveEditMode {
get { return (PropertyContainerEditMode)this.GetValue(PropertyContainer.ActiveEditModeProperty); }
set { this.SetValue(PropertyContainer.ActiveEditModeProperty, value); }
}
private static void OnActiveEditModePropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) {
PropertyContainer theThis = (PropertyContainer)obj;
// Ensure that the Template property of this control is set to the right ControlTemplate
UpdateControlTemplate(theThis);
// Invoke a dialog editor if needed
if (object.Equals(e.NewValue, PropertyContainerEditMode.Dialog)) {
if (OpenDialogWindow.CanExecute(null, theThis)) {
// There is someone who handles this command, so let it deal with it
// however it wants.
OpenDialogWindow.Execute(null, theThis);
}
else {
// There is no-one handling this command, so see if there is a virtual
// method we can invoke
DialogPropertyValueEditor editor = theThis.FindDialogPropertyValueEditor();
if (editor != null) {
// If the DialogCommandSource is not explicitly set, use this control as the
// command source
IInputElement dialogCommandSource = theThis.DialogCommandSource ?? theThis;
editor.ShowDialog(theThis.PropertyEntry.PropertyValue, dialogCommandSource);
}
}
// And revert back to old edit mode once done
theThis.ActiveEditMode = (PropertyContainerEditMode)e.OldValue;
}
}
// DialogCommandSource DP
///
/// Gets or sets the IInputElement to pass into the ShowDialog() method as the command source.
/// If null (default), _this_ will be passed in.
/// Note: ShowDialog() method is called on a DialogPropertyValueEditor instance if a dialog editor
/// is invoked and the editor does not specify any dialog DataTemplate.
///
public static readonly DependencyProperty DialogCommandSourceProperty =
DependencyProperty.Register(
"DialogCommandSource",
typeof(IInputElement),
typeof(PropertyContainer),
new PropertyMetadata((IInputElement)null));
///
/// Gets or sets the IInputElement to pass into the ShowDialog() method as the command source.
/// If null (default), _this_ will be passed in.
/// Note: ShowDialog() method is called on a DialogPropertyValueEditor instance if a dialog editor
/// is invoked and the editor does not specify any dialog DataTemplate.
///
[Fx.Tag.KnownXamlExternalAttribute]
public IInputElement DialogCommandSource
{
get { return (IInputElement)this.GetValue(DialogCommandSourceProperty); }
set { this.SetValue(DialogCommandSourceProperty, value); }
}
// OwningPropertyContainer Attached, Inherited DP
///
/// Attached, inherited DP that can be used by UI elements of PropertyValueEditors
/// to gain access to their parent PropertyContainer.
///
public static readonly DependencyProperty OwningPropertyContainerProperty =
DependencyProperty.RegisterAttached(
"OwningPropertyContainer",
typeof(PropertyContainer),
typeof(PropertyContainer),
new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.Inherits));
///
/// Setter for attached, inherited DP that can be used by UI elements of PropertyValueEditors
/// to gain access to their parent PropertyContainer.
///
/// The DO to set the property on
/// The Owning PropertyContainer
public static void SetOwningPropertyContainer(DependencyObject dependencyObject, PropertyContainer value) {
if (dependencyObject == null)
throw FxTrace.Exception.ArgumentNull("dependencyObject");
dependencyObject.SetValue(PropertyContainer.OwningPropertyContainerProperty, value);
}
///
/// Getter for attached, inherited DP that can be used by UI elements of PropertyValueEditors
/// to gain access to their parent PropertyContainer.
///
/// The DO to get the property from
/// The owning PropertyContainer
public static PropertyContainer GetOwningPropertyContainer(DependencyObject dependencyObject) {
if (dependencyObject == null)
throw FxTrace.Exception.ArgumentNull("dependencyObject");
return (PropertyContainer)dependencyObject.GetValue(PropertyContainer.OwningPropertyContainerProperty);
}
// ControlTemplates for PropertyContainer to define the UI for the different edit modes
// InlineRowTemplate DP
///
/// This DP is used to get/set the InlineRowTemplate for the PropertyContainer. The
/// InlineRowTemplate defines how the PropertyContainer renders itself when
/// ActiveEditMode = Inline.
///
public static readonly DependencyProperty InlineRowTemplateProperty =
DependencyProperty.Register(
"InlineRowTemplate",
typeof(ControlTemplate),
typeof(PropertyContainer),
new FrameworkPropertyMetadata(
null,
FrameworkPropertyMetadataOptions.None,
new PropertyChangedCallback(RowTemplateChanged)));
///
/// Gets or sets the InlineRowTemplate for the PropertyContainer. The
/// InlineRowTemplate defines how the PropertyContainer renders itself when
/// ActiveEditMode = Inline.
///
[Fx.Tag.KnownXamlExternalAttribute]
public ControlTemplate InlineRowTemplate
{
get { return (ControlTemplate)this.GetValue(PropertyContainer.InlineRowTemplateProperty); }
set { this.SetValue(PropertyContainer.InlineRowTemplateProperty, value); }
}
// Called when any of the row templates (InlineRowTemplate, ExtendedPopupRowTemplate, ExtendedPinnedRowTemplate)
// change
private static void RowTemplateChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) {
PropertyContainer theThis = (PropertyContainer)obj;
bool updateControlTemplate = false;
// Check InlineRowTemplate
updateControlTemplate = updateControlTemplate |
(e.Property == PropertyContainer.InlineRowTemplateProperty &&
theThis.ActiveEditMode == PropertyContainerEditMode.Inline);
// Check ExtendedPopup
updateControlTemplate = updateControlTemplate |
(e.Property == PropertyContainer.ExtendedPopupRowTemplateProperty &&
theThis.ActiveEditMode == PropertyContainerEditMode.ExtendedPopup);
// Check ExtendedPinned
updateControlTemplate = updateControlTemplate |
(e.Property == PropertyContainer.ExtendedPinnedRowTemplateProperty &&
theThis.ActiveEditMode == PropertyContainerEditMode.ExtendedPinned);
if (updateControlTemplate)
UpdateControlTemplate(theThis);
}
// ExtendedPopupRowTemplate DP
///
/// This DP is used to get/set the ExtendedPopupRowTemplate for this PropertyContainer.
/// The ExtendedPopupRowTemplate defines how the PropertyContainer renders itself when
/// ActiveEditMode = ExtendedPopup. Generally, host implementations will define this
/// template to automatically include the InlineRowTemplate as well.
///
public static readonly DependencyProperty ExtendedPopupRowTemplateProperty =
DependencyProperty.Register(
"ExtendedPopupRowTemplate",
typeof(ControlTemplate),
typeof(PropertyContainer),
new FrameworkPropertyMetadata(
null,
FrameworkPropertyMetadataOptions.None,
new PropertyChangedCallback(RowTemplateChanged)));
///
/// Gets or sets the ExtendedPopupRowTemplate for this PropertyContainer.
/// The ExtendedPopupRowTemplate defines how the PropertyContainer renders itself when
/// ActiveEditMode = ExtendedPopup. Generally, host implementations will define this
/// template to automatically include the InlineRowTemplate as well.
///
[Fx.Tag.KnownXamlExternalAttribute]
public ControlTemplate ExtendedPopupRowTemplate
{
get { return (ControlTemplate)this.GetValue(PropertyContainer.ExtendedPopupRowTemplateProperty); }
set { this.SetValue(PropertyContainer.ExtendedPopupRowTemplateProperty, value); }
}
// ExtendedPinnedRowTemplate DP
///
/// This DP is used to get/set the ExtendedPinnedRowTemplate for this PropertyContainer.
/// The ExtendedPinnedRowTemplate defines how the PropertyContainer renders itself when
/// ActiveEditMode = ExtendedPinned. Generally, host implementations will define this
/// template to automatically include the InlineRowTemplate as well.
///
public static readonly DependencyProperty ExtendedPinnedRowTemplateProperty =
DependencyProperty.Register(
"ExtendedPinnedRowTemplate",
typeof(ControlTemplate),
typeof(PropertyContainer),
new FrameworkPropertyMetadata(
null,
FrameworkPropertyMetadataOptions.None,
new PropertyChangedCallback(RowTemplateChanged)));
///
/// Get/set the ExtendedPinnedRowTemplate for this PropertyContainer.
/// The ExtendedPinnedRowTemplate defines how the PropertyContainer renders itself when
/// ActiveEditMode = ExtendedPinned. Generally, host implementations will define this
/// template to automatically include the InlineRowTemplate as well.
///
[Fx.Tag.KnownXamlExternalAttribute]
public ControlTemplate ExtendedPinnedRowTemplate
{
get { return (ControlTemplate)this.GetValue(PropertyContainer.ExtendedPinnedRowTemplateProperty); }
set { this.SetValue(PropertyContainer.ExtendedPinnedRowTemplateProperty, value); }
}
// Default PropertyValueEditors to use when a given property doesn't specify its own
// DefaultStandardValuesPropertyValueEditor DP
///
/// DP to get or set the default standard-values editor which is used when a PropertyEntry supports
/// StandardValues (enum or through a TypeConverter) and there isn't a PropertyValueEditor
/// defined for the PropertyEntry or Type explicitely.
///
public static readonly DependencyProperty DefaultStandardValuesPropertyValueEditorProperty =
DependencyProperty.Register(
"DefaultStandardValuesPropertyValueEditor",
typeof(PropertyValueEditor),
typeof(PropertyContainer),
new FrameworkPropertyMetadata(
null,
new PropertyChangedCallback(DefaultPropertyValueEditorChanged)));
///
/// Gets or set the default standard-values editor which is used when a PropertyEntry supports
/// StandardValues (enum or through a TypeConverter) and there isn't a PropertyValueEditor
/// defined for the PropertyEntry or Type explicitely.
///
[Fx.Tag.KnownXamlExternalAttribute]
public PropertyValueEditor DefaultStandardValuesPropertyValueEditor
{
get { return (PropertyValueEditor)this.GetValue(PropertyContainer.DefaultStandardValuesPropertyValueEditorProperty); }
set { this.SetValue(PropertyContainer.DefaultStandardValuesPropertyValueEditorProperty, value); }
}
private static void DefaultPropertyValueEditorChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) {
PropertyContainer theThis = (PropertyContainer)obj;
// Since one of the default PVE's has changed, chances are that the Inline or the Extended
// editor template has changed as well.
theThis.NotifyTemplatesChanged();
}
// DefaultPropertyValueEditor DP
///
/// DP to get or set the default PropertyValueEditor which is the editor used when the
/// PropertyEntry or Type does not explicitely define its own PropertyValueEditor and does not
/// support StandardValues.
///
public static readonly DependencyProperty DefaultPropertyValueEditorProperty =
DependencyProperty.Register(
"DefaultPropertyValueEditor",
typeof(PropertyValueEditor),
typeof(PropertyContainer),
new FrameworkPropertyMetadata(
null,
new PropertyChangedCallback(DefaultPropertyValueEditorChanged)));
///
/// Gets or sets the default PropertyValueEditor which is the editor used when the
/// PropertyEntry or Type does not explicitely define its own PropertyValueEditor and does not
/// support StandardValues.
///
[Fx.Tag.KnownXamlExternalAttribute]
public PropertyValueEditor DefaultPropertyValueEditor
{
get { return (PropertyValueEditor)this.GetValue(PropertyContainer.DefaultPropertyValueEditorProperty); }
set { this.SetValue(PropertyContainer.DefaultPropertyValueEditorProperty, value); }
}
// Regular properties (read-only values for DataBinding)
// InlineEditorTemplate read-only CLR property
///
/// Gets the most appropriate InlineEditorTemplate for the current PropertyEntry.
/// A row template may decide to use this value to render the editor on the appropriate place.
///
[Fx.Tag.KnownXamlExternalAttribute]
public DataTemplate InlineEditorTemplate
{
get {
return FindPropertyValueEditorTemplate(PropertyContainerEditMode.Inline);
}
}
// ExtendedEditorTemplate read-only CLR property
///
/// Gets the most appropriate ExtendedEditorTemplate for the current PropertyEntry.
/// A row template may decide to use this value to render the editor on the appropriate place.
///
[Fx.Tag.KnownXamlExternalAttribute]
public DataTemplate ExtendedEditorTemplate
{
get {
return FindPropertyValueEditorTemplate(PropertyContainerEditMode.ExtendedPinned);
}
}
// DialogEditorTemplate read-only CLR property
///
/// Gets the most appropriate DialogEditorTemplate for the current PropertyEntry.
/// A row template or a Dialog may decide to use this value to render the editor on the
/// appropriate place.
///
[Fx.Tag.KnownXamlExternalAttribute]
public DataTemplate DialogEditorTemplate {
get {
return FindPropertyValueEditorTemplate(PropertyContainerEditMode.Dialog);
}
}
// MatchesFilter read-only CLR property
///
/// Gets the value for MatchesFilter stored in the contained PropertyEntry. If the PropertyEntry
/// is null, the value returned is false.
/// This property can be used to trigger UI changes to the PropertyContainer based on
/// whether the current PropertyEntry matches the current filter or not.
///
public bool MatchesFilter {
get {
PropertyEntry property = this.PropertyEntry;
return property != null && property.MatchesFilter;
}
}
// OpenDialogWindow static, read-only command property
///
/// Gets the command that is fired when someone changes the ActiveEditMode property to "Dialog".
/// The host may choose to handle this command and, display the DialogEditorTemplate
/// (if one exists) in a host-specific dialog container. If the host does not handle
/// this command (OpenDialogWindow.CanExecute is false), the PropertyContainer itself
/// defaults to calling into the virtual DialogPropertyValueEditor.ShowDialog()
/// method, but only if DialogPropertyValueEditor is found.
///
public static RoutedCommand OpenDialogWindow {
get {
if (_openDialogWindow == null)
_openDialogWindow = new RoutedCommand("OpenDialogWindow", typeof(PropertyContainer));
return _openDialogWindow;
}
}
internal bool SupportsEditMode(PropertyContainerEditMode mode) {
// special handling for dialog editor
if (mode == PropertyContainerEditMode.Dialog)
return FindDialogPropertyValueEditor() != null;
// for everything else
return FindPropertyValueEditorTemplate(mode) != null;
}
// When the control gets unloaded, unhook any remaining event handlers
// so that it can be garbage collected
private void OnUnloaded(object sender, RoutedEventArgs e) {
PropertyEntry entry = this.PropertyEntry;
if (entry != null)
DisassociatePropertyEventHandlers(entry);
}
// When the control gets re-loaded, re-hook any previous event handlers
// that may have been disassociated during Unload
private void OnLoaded(object sender, RoutedEventArgs e) {
PropertyEntry entry = this.PropertyEntry;
if (entry != null)
AssociatePropertyEventHandlers(entry);
}
// Helper that hooks into PropertyChanged events on the given Property
private void AssociatePropertyEventHandlers(PropertyEntry property) {
if (!_attachedToPropertyEntryEvents) {
property.PropertyChanged += new PropertyChangedEventHandler(OnPropertyPropertyChanged);
_attachedToPropertyEntryEvents = true;
}
}
// Helper that unhooks from PropertyChanged events on the given Property
private void DisassociatePropertyEventHandlers(PropertyEntry property) {
if (_attachedToPropertyEntryEvents) {
property.PropertyChanged -= new PropertyChangedEventHandler(OnPropertyPropertyChanged);
_attachedToPropertyEntryEvents = false;
}
}
// Called when the properties of the Property object change
private void OnPropertyPropertyChanged(object sender, PropertyChangedEventArgs e) {
// Propagate MatchesFilter change notifications outwards so that
// people can set up triggers against it
if ("MatchesFilter".Equals(e.PropertyName))
this.OnPropertyChanged("MatchesFilter");
else if ("PropertyValueEditor".Equals(e.PropertyName))
this.NotifyTemplatesChanged();
}
///
/// Helper class that attempts to find the DataTemplate for the requested PropertyContainerEditMode
/// given the currently displayed PropertyEntry and the currently set default PropertyValueEditors.
///
/// If the requested DataTemplate is found on the PropertyValueEditor associated with the displayed
/// control, is it returned.
///
/// Otherwise if the requested DataTemplate is found on DefaultStandardValuesPropertyValueEditor,
/// it is returned.
///
/// Otherwise if the requested DataTemplate is found on DefaultPropertyValueEditor,
/// it is returned.
///
/// Otherwise null is returned.
///
/// The editMode for which the DataTemplate should be retrieved
/// Most relevant DataTemplate for the specified edit mode based on the currently
/// displayed PropertyEntry and the current set of default PropertyValueEditors, or null if not
/// found.
private DataTemplate FindPropertyValueEditorTemplate(PropertyContainerEditMode editMode) {
PropertyEntry property = this.PropertyEntry;
PropertyValueEditor editor = null;
DataTemplate requestedTemplate = null;
// Look at property
if (property != null) {
editor = property.PropertyValueEditor;
if (editor != null) {
requestedTemplate = editor.GetPropertyValueEditor(editMode);
}
}
if (requestedTemplate != null)
return requestedTemplate;
// Is the property of type enum and used as flags?
if (IsFlagsProperty(property))
{
requestedTemplate = this.GetFlagEditorTemplate(editMode);
}
if (requestedTemplate != null)
{
return requestedTemplate;
}
// Does the property have standard values?
if (property != null && property.HasStandardValuesInternal) {
editor = this.DefaultStandardValuesPropertyValueEditor;
if (editor != null) {
requestedTemplate = editor.GetPropertyValueEditor(editMode);
}
}
if (requestedTemplate != null)
return requestedTemplate;
// Use the default
editor = this.DefaultPropertyValueEditor;
if (editor != null) {
requestedTemplate = editor.GetPropertyValueEditor(editMode);
}
return requestedTemplate;
}
bool IsFlagsProperty(PropertyEntry property)
{
return property != null && property.PropertyType != null && property.PropertyType.IsEnum &&
ExtensibilityAccessor.GetAttribute(property.PropertyType) != null;
}
DataTemplate GetFlagEditorTemplate(PropertyContainerEditMode editMode)
{
Type propertyType = this.PropertyEntry.PropertyType;
if (editMode == PropertyContainerEditMode.Inline)
{
if(this.flagEditorTemplate == null)
{
this.flagEditorTemplate = new DataTemplate();
this.flagEditorTemplate.VisualTree = new FrameworkElementFactory(typeof(FlagEditor));
this.flagEditorTemplate.VisualTree.SetValue(FlagEditor.FlagTypeProperty, propertyType);
Binding binding = new Binding("Value");
binding.Converter = new FlagStringConverter();
binding.ConverterParameter = propertyType;
binding.UpdateSourceTrigger = UpdateSourceTrigger.Explicit;
this.flagEditorTemplate.VisualTree.SetBinding(FlagEditor.TextProperty, binding);
}
return this.flagEditorTemplate;
}
else
{
return null;
}
}
// Helper that tries to find the first applicable DialogPropertyValueEditor
private DialogPropertyValueEditor FindDialogPropertyValueEditor() {
PropertyEntry property = this.PropertyEntry;
DialogPropertyValueEditor editor = null;
// Look at property
if (property != null) {
editor = property.PropertyValueEditor as DialogPropertyValueEditor;
}
if (editor != null)
return editor;
// Does the property have standard values?
if (property != null && property.HasStandardValuesInternal) {
editor = this.DefaultStandardValuesPropertyValueEditor as DialogPropertyValueEditor;
}
if (editor != null)
return editor;
// Use the default
editor = this.DefaultPropertyValueEditor as DialogPropertyValueEditor;
return editor;
}
// Updates the ControlTemplate of this control based on the currently ActiveEditMode
private static void UpdateControlTemplate(PropertyContainer container) {
PropertyContainerEditMode editMode = container.ActiveEditMode;
ControlTemplate newTemplate = null;
switch (editMode) {
case PropertyContainerEditMode.Inline:
newTemplate = container.InlineRowTemplate;
break;
case PropertyContainerEditMode.ExtendedPopup:
newTemplate = container.ExtendedPopupRowTemplate;
break;
case PropertyContainerEditMode.ExtendedPinned:
newTemplate = container.ExtendedPinnedRowTemplate;
break;
case PropertyContainerEditMode.Dialog:
// In dialog case, just keep the same value
return;
default:
Debug.Fail(
string.Format(
System.Globalization.CultureInfo.CurrentCulture,
"PropertyContainerEditMode does not yet support PropertyContainerEditMode '{0}'.",
editMode.ToString()));
newTemplate = container.Template;
break;
}
if (newTemplate != container.Template)
container.Template = newTemplate;
}
private void NotifyTemplatesChanged() {
OnPropertyChanged("InlineEditorTemplate");
OnPropertyChanged("ExtendedEditorTemplate");
OnPropertyChanged("DialogEditorTemplate");
}
///
/// Called when a property changes
///
/// Name of the property
protected virtual void OnPropertyChanged(string propertyName) {
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
///
/// Called when a property changes
///
/// Name of the property
protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e) {
if (DependencyPropertyChanged != null)
DependencyPropertyChanged(this, e);
base.OnPropertyChanged(e);
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
namespace System.Activities.Presentation.PropertyEditing {
using System.Windows.Controls;
using System.Windows;
using System;
using System.Windows.Data;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Windows.Input;
using System.Windows.Controls.Primitives;
using System.Windows.Media;
using System.ComponentModel;
using System.Collections.Generic;
using System.Activities.Presentation;
using System.Runtime;
using System.Activities.Presentation.Internal.PropertyEditing.Editors;
using System.Activities.Presentation.Internal.PropertyEditing;
///
/// This control is used as a graphical container for PropertyEntry instances. The control is
/// look-less. However, it is generally styled as a horizontal row that includes the
/// name of the property followed by an editor for its value. This control, however, is
/// intended to be restiled by 3rd-parties to suite their needs. The style is controled
/// by three ControlTemplates (InlineRowTemplate, ExtendedPopupRowTemplate, and
/// ExtendedPinnedRowTemplate) that are chosed by the logic within this control based
/// on the current value of ActiveEditMode. This control also exposes three DataTemplates
/// (InlineEditor, ExtendedEditor, and DialogEditor) that each of the row templates can use
/// to display the appropriate value editor for the PropertyValue being edited.
///
class PropertyContainer : Control, INotifyPropertyChanged {
private static RoutedCommand _openDialogWindow;
DataTemplate flagEditorTemplate;
///
/// INotifyPropertyChanged event
///
public event PropertyChangedEventHandler PropertyChanged;
internal event DependencyPropertyChangedEventHandler DependencyPropertyChanged;
private bool _attachedToPropertyEntryEvents;
///
/// Creates a PropertyContainer
///
[SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public PropertyContainer() {
// Set the OwningPropertyContainer (attached, inherited DP) to self,
// so that all of the children of this control know which PropertyContainer
// they belong to
SetOwningPropertyContainer(this, this);
this.Loaded += new RoutedEventHandler(OnLoaded);
this.Unloaded += new RoutedEventHandler(OnUnloaded);
}
// Useful DPs
// PropertyEntry DP
public static readonly DependencyProperty IsValueEditEnabledProperty = DependencyProperty.Register(
"IsValueEditEnabled",
typeof(bool),
typeof(PropertyContainer),
new UIPropertyMetadata(true));
///
/// Gets or sets the PropertyEntry instance on which this PropertyContainer operates.
/// That is the context of the PropertyContainer. The exposed editor templates
/// (InlineEditor, ExtendedEditor, and DialogEditor) are based on the value of this property.
///
public static readonly DependencyProperty PropertyEntryProperty =
DependencyProperty.Register(
"PropertyEntry",
typeof(PropertyEntry),
typeof(PropertyContainer),
new FrameworkPropertyMetadata(
null,
new PropertyChangedCallback(PropertyEntryPropertyChanged)));
///
/// Gets or sets the PropertyEntry instance on which this PropertyContainer operates.
/// That is the context of the PropertyContainer. The exposed editor templates
/// (InlineEditor, ExtendedEditor, and DialogEditor) are based on the value of this property.
///
[Fx.Tag.KnownXamlExternalAttribute]
public PropertyEntry PropertyEntry
{
get { return (PropertyEntry)this.GetValue(PropertyContainer.PropertyEntryProperty); }
set { this.SetValue(PropertyContainer.PropertyEntryProperty, value); }
}
public bool IsValueEditEnabled
{
get { return (bool)GetValue(IsValueEditEnabledProperty); }
set { SetValue(IsValueEditEnabledProperty, value); }
}
private static void PropertyEntryPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) {
PropertyContainer theThis = (PropertyContainer)obj;
// Since the underlying property has changed, chances are that the inline or extended editors
// have changed as well, so fire events indicating that their values have changed
theThis.NotifyTemplatesChanged();
theThis.OnPropertyChanged("MatchesFilter");
// Switch back to Inline mode
theThis.ActiveEditMode = PropertyContainerEditMode.Inline;
// Ensure that the Template property of this control is set to the right ControlTemplate
UpdateControlTemplate(theThis);
// Hook into PropertyEntry's changed events
if (e.OldValue != null)
theThis.DisassociatePropertyEventHandlers((PropertyEntry)e.OldValue);
if (e.NewValue != null)
theThis.AssociatePropertyEventHandlers((PropertyEntry)e.NewValue);
}
// ActiveEditMode DP
//
///
/// Gets or sets currently displayed edit mode of this container (ie. ExtendedPopup,
/// ExtendedPinned, Inline or Dialog).
///
public static readonly DependencyProperty ActiveEditModeProperty =
DependencyProperty.Register(
"ActiveEditMode",
typeof(PropertyContainerEditMode),
typeof(PropertyContainer),
new FrameworkPropertyMetadata(
PropertyContainerEditMode.Inline,
new PropertyChangedCallback(OnActiveEditModePropertyChanged)));
///
/// Gets or sets currently displayed edit mode of this container (ie. ExtendedPopup,
/// ExtendedPinned, Inline or Dialog).
///
public PropertyContainerEditMode ActiveEditMode {
get { return (PropertyContainerEditMode)this.GetValue(PropertyContainer.ActiveEditModeProperty); }
set { this.SetValue(PropertyContainer.ActiveEditModeProperty, value); }
}
private static void OnActiveEditModePropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) {
PropertyContainer theThis = (PropertyContainer)obj;
// Ensure that the Template property of this control is set to the right ControlTemplate
UpdateControlTemplate(theThis);
// Invoke a dialog editor if needed
if (object.Equals(e.NewValue, PropertyContainerEditMode.Dialog)) {
if (OpenDialogWindow.CanExecute(null, theThis)) {
// There is someone who handles this command, so let it deal with it
// however it wants.
OpenDialogWindow.Execute(null, theThis);
}
else {
// There is no-one handling this command, so see if there is a virtual
// method we can invoke
DialogPropertyValueEditor editor = theThis.FindDialogPropertyValueEditor();
if (editor != null) {
// If the DialogCommandSource is not explicitly set, use this control as the
// command source
IInputElement dialogCommandSource = theThis.DialogCommandSource ?? theThis;
editor.ShowDialog(theThis.PropertyEntry.PropertyValue, dialogCommandSource);
}
}
// And revert back to old edit mode once done
theThis.ActiveEditMode = (PropertyContainerEditMode)e.OldValue;
}
}
// DialogCommandSource DP
///
/// Gets or sets the IInputElement to pass into the ShowDialog() method as the command source.
/// If null (default), _this_ will be passed in.
/// Note: ShowDialog() method is called on a DialogPropertyValueEditor instance if a dialog editor
/// is invoked and the editor does not specify any dialog DataTemplate.
///
public static readonly DependencyProperty DialogCommandSourceProperty =
DependencyProperty.Register(
"DialogCommandSource",
typeof(IInputElement),
typeof(PropertyContainer),
new PropertyMetadata((IInputElement)null));
///
/// Gets or sets the IInputElement to pass into the ShowDialog() method as the command source.
/// If null (default), _this_ will be passed in.
/// Note: ShowDialog() method is called on a DialogPropertyValueEditor instance if a dialog editor
/// is invoked and the editor does not specify any dialog DataTemplate.
///
[Fx.Tag.KnownXamlExternalAttribute]
public IInputElement DialogCommandSource
{
get { return (IInputElement)this.GetValue(DialogCommandSourceProperty); }
set { this.SetValue(DialogCommandSourceProperty, value); }
}
// OwningPropertyContainer Attached, Inherited DP
///
/// Attached, inherited DP that can be used by UI elements of PropertyValueEditors
/// to gain access to their parent PropertyContainer.
///
public static readonly DependencyProperty OwningPropertyContainerProperty =
DependencyProperty.RegisterAttached(
"OwningPropertyContainer",
typeof(PropertyContainer),
typeof(PropertyContainer),
new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.Inherits));
///
/// Setter for attached, inherited DP that can be used by UI elements of PropertyValueEditors
/// to gain access to their parent PropertyContainer.
///
/// The DO to set the property on
/// The Owning PropertyContainer
public static void SetOwningPropertyContainer(DependencyObject dependencyObject, PropertyContainer value) {
if (dependencyObject == null)
throw FxTrace.Exception.ArgumentNull("dependencyObject");
dependencyObject.SetValue(PropertyContainer.OwningPropertyContainerProperty, value);
}
///
/// Getter for attached, inherited DP that can be used by UI elements of PropertyValueEditors
/// to gain access to their parent PropertyContainer.
///
/// The DO to get the property from
/// The owning PropertyContainer
public static PropertyContainer GetOwningPropertyContainer(DependencyObject dependencyObject) {
if (dependencyObject == null)
throw FxTrace.Exception.ArgumentNull("dependencyObject");
return (PropertyContainer)dependencyObject.GetValue(PropertyContainer.OwningPropertyContainerProperty);
}
// ControlTemplates for PropertyContainer to define the UI for the different edit modes
// InlineRowTemplate DP
///
/// This DP is used to get/set the InlineRowTemplate for the PropertyContainer. The
/// InlineRowTemplate defines how the PropertyContainer renders itself when
/// ActiveEditMode = Inline.
///
public static readonly DependencyProperty InlineRowTemplateProperty =
DependencyProperty.Register(
"InlineRowTemplate",
typeof(ControlTemplate),
typeof(PropertyContainer),
new FrameworkPropertyMetadata(
null,
FrameworkPropertyMetadataOptions.None,
new PropertyChangedCallback(RowTemplateChanged)));
///
/// Gets or sets the InlineRowTemplate for the PropertyContainer. The
/// InlineRowTemplate defines how the PropertyContainer renders itself when
/// ActiveEditMode = Inline.
///
[Fx.Tag.KnownXamlExternalAttribute]
public ControlTemplate InlineRowTemplate
{
get { return (ControlTemplate)this.GetValue(PropertyContainer.InlineRowTemplateProperty); }
set { this.SetValue(PropertyContainer.InlineRowTemplateProperty, value); }
}
// Called when any of the row templates (InlineRowTemplate, ExtendedPopupRowTemplate, ExtendedPinnedRowTemplate)
// change
private static void RowTemplateChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) {
PropertyContainer theThis = (PropertyContainer)obj;
bool updateControlTemplate = false;
// Check InlineRowTemplate
updateControlTemplate = updateControlTemplate |
(e.Property == PropertyContainer.InlineRowTemplateProperty &&
theThis.ActiveEditMode == PropertyContainerEditMode.Inline);
// Check ExtendedPopup
updateControlTemplate = updateControlTemplate |
(e.Property == PropertyContainer.ExtendedPopupRowTemplateProperty &&
theThis.ActiveEditMode == PropertyContainerEditMode.ExtendedPopup);
// Check ExtendedPinned
updateControlTemplate = updateControlTemplate |
(e.Property == PropertyContainer.ExtendedPinnedRowTemplateProperty &&
theThis.ActiveEditMode == PropertyContainerEditMode.ExtendedPinned);
if (updateControlTemplate)
UpdateControlTemplate(theThis);
}
// ExtendedPopupRowTemplate DP
///
/// This DP is used to get/set the ExtendedPopupRowTemplate for this PropertyContainer.
/// The ExtendedPopupRowTemplate defines how the PropertyContainer renders itself when
/// ActiveEditMode = ExtendedPopup. Generally, host implementations will define this
/// template to automatically include the InlineRowTemplate as well.
///
public static readonly DependencyProperty ExtendedPopupRowTemplateProperty =
DependencyProperty.Register(
"ExtendedPopupRowTemplate",
typeof(ControlTemplate),
typeof(PropertyContainer),
new FrameworkPropertyMetadata(
null,
FrameworkPropertyMetadataOptions.None,
new PropertyChangedCallback(RowTemplateChanged)));
///
/// Gets or sets the ExtendedPopupRowTemplate for this PropertyContainer.
/// The ExtendedPopupRowTemplate defines how the PropertyContainer renders itself when
/// ActiveEditMode = ExtendedPopup. Generally, host implementations will define this
/// template to automatically include the InlineRowTemplate as well.
///
[Fx.Tag.KnownXamlExternalAttribute]
public ControlTemplate ExtendedPopupRowTemplate
{
get { return (ControlTemplate)this.GetValue(PropertyContainer.ExtendedPopupRowTemplateProperty); }
set { this.SetValue(PropertyContainer.ExtendedPopupRowTemplateProperty, value); }
}
// ExtendedPinnedRowTemplate DP
///
/// This DP is used to get/set the ExtendedPinnedRowTemplate for this PropertyContainer.
/// The ExtendedPinnedRowTemplate defines how the PropertyContainer renders itself when
/// ActiveEditMode = ExtendedPinned. Generally, host implementations will define this
/// template to automatically include the InlineRowTemplate as well.
///
public static readonly DependencyProperty ExtendedPinnedRowTemplateProperty =
DependencyProperty.Register(
"ExtendedPinnedRowTemplate",
typeof(ControlTemplate),
typeof(PropertyContainer),
new FrameworkPropertyMetadata(
null,
FrameworkPropertyMetadataOptions.None,
new PropertyChangedCallback(RowTemplateChanged)));
///
/// Get/set the ExtendedPinnedRowTemplate for this PropertyContainer.
/// The ExtendedPinnedRowTemplate defines how the PropertyContainer renders itself when
/// ActiveEditMode = ExtendedPinned. Generally, host implementations will define this
/// template to automatically include the InlineRowTemplate as well.
///
[Fx.Tag.KnownXamlExternalAttribute]
public ControlTemplate ExtendedPinnedRowTemplate
{
get { return (ControlTemplate)this.GetValue(PropertyContainer.ExtendedPinnedRowTemplateProperty); }
set { this.SetValue(PropertyContainer.ExtendedPinnedRowTemplateProperty, value); }
}
// Default PropertyValueEditors to use when a given property doesn't specify its own
// DefaultStandardValuesPropertyValueEditor DP
///
/// DP to get or set the default standard-values editor which is used when a PropertyEntry supports
/// StandardValues (enum or through a TypeConverter) and there isn't a PropertyValueEditor
/// defined for the PropertyEntry or Type explicitely.
///
public static readonly DependencyProperty DefaultStandardValuesPropertyValueEditorProperty =
DependencyProperty.Register(
"DefaultStandardValuesPropertyValueEditor",
typeof(PropertyValueEditor),
typeof(PropertyContainer),
new FrameworkPropertyMetadata(
null,
new PropertyChangedCallback(DefaultPropertyValueEditorChanged)));
///
/// Gets or set the default standard-values editor which is used when a PropertyEntry supports
/// StandardValues (enum or through a TypeConverter) and there isn't a PropertyValueEditor
/// defined for the PropertyEntry or Type explicitely.
///
[Fx.Tag.KnownXamlExternalAttribute]
public PropertyValueEditor DefaultStandardValuesPropertyValueEditor
{
get { return (PropertyValueEditor)this.GetValue(PropertyContainer.DefaultStandardValuesPropertyValueEditorProperty); }
set { this.SetValue(PropertyContainer.DefaultStandardValuesPropertyValueEditorProperty, value); }
}
private static void DefaultPropertyValueEditorChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) {
PropertyContainer theThis = (PropertyContainer)obj;
// Since one of the default PVE's has changed, chances are that the Inline or the Extended
// editor template has changed as well.
theThis.NotifyTemplatesChanged();
}
// DefaultPropertyValueEditor DP
///
/// DP to get or set the default PropertyValueEditor which is the editor used when the
/// PropertyEntry or Type does not explicitely define its own PropertyValueEditor and does not
/// support StandardValues.
///
public static readonly DependencyProperty DefaultPropertyValueEditorProperty =
DependencyProperty.Register(
"DefaultPropertyValueEditor",
typeof(PropertyValueEditor),
typeof(PropertyContainer),
new FrameworkPropertyMetadata(
null,
new PropertyChangedCallback(DefaultPropertyValueEditorChanged)));
///
/// Gets or sets the default PropertyValueEditor which is the editor used when the
/// PropertyEntry or Type does not explicitely define its own PropertyValueEditor and does not
/// support StandardValues.
///
[Fx.Tag.KnownXamlExternalAttribute]
public PropertyValueEditor DefaultPropertyValueEditor
{
get { return (PropertyValueEditor)this.GetValue(PropertyContainer.DefaultPropertyValueEditorProperty); }
set { this.SetValue(PropertyContainer.DefaultPropertyValueEditorProperty, value); }
}
// Regular properties (read-only values for DataBinding)
// InlineEditorTemplate read-only CLR property
///
/// Gets the most appropriate InlineEditorTemplate for the current PropertyEntry.
/// A row template may decide to use this value to render the editor on the appropriate place.
///
[Fx.Tag.KnownXamlExternalAttribute]
public DataTemplate InlineEditorTemplate
{
get {
return FindPropertyValueEditorTemplate(PropertyContainerEditMode.Inline);
}
}
// ExtendedEditorTemplate read-only CLR property
///
/// Gets the most appropriate ExtendedEditorTemplate for the current PropertyEntry.
/// A row template may decide to use this value to render the editor on the appropriate place.
///
[Fx.Tag.KnownXamlExternalAttribute]
public DataTemplate ExtendedEditorTemplate
{
get {
return FindPropertyValueEditorTemplate(PropertyContainerEditMode.ExtendedPinned);
}
}
// DialogEditorTemplate read-only CLR property
///
/// Gets the most appropriate DialogEditorTemplate for the current PropertyEntry.
/// A row template or a Dialog may decide to use this value to render the editor on the
/// appropriate place.
///
[Fx.Tag.KnownXamlExternalAttribute]
public DataTemplate DialogEditorTemplate {
get {
return FindPropertyValueEditorTemplate(PropertyContainerEditMode.Dialog);
}
}
// MatchesFilter read-only CLR property
///
/// Gets the value for MatchesFilter stored in the contained PropertyEntry. If the PropertyEntry
/// is null, the value returned is false.
/// This property can be used to trigger UI changes to the PropertyContainer based on
/// whether the current PropertyEntry matches the current filter or not.
///
public bool MatchesFilter {
get {
PropertyEntry property = this.PropertyEntry;
return property != null && property.MatchesFilter;
}
}
// OpenDialogWindow static, read-only command property
///
/// Gets the command that is fired when someone changes the ActiveEditMode property to "Dialog".
/// The host may choose to handle this command and, display the DialogEditorTemplate
/// (if one exists) in a host-specific dialog container. If the host does not handle
/// this command (OpenDialogWindow.CanExecute is false), the PropertyContainer itself
/// defaults to calling into the virtual DialogPropertyValueEditor.ShowDialog()
/// method, but only if DialogPropertyValueEditor is found.
///
public static RoutedCommand OpenDialogWindow {
get {
if (_openDialogWindow == null)
_openDialogWindow = new RoutedCommand("OpenDialogWindow", typeof(PropertyContainer));
return _openDialogWindow;
}
}
internal bool SupportsEditMode(PropertyContainerEditMode mode) {
// special handling for dialog editor
if (mode == PropertyContainerEditMode.Dialog)
return FindDialogPropertyValueEditor() != null;
// for everything else
return FindPropertyValueEditorTemplate(mode) != null;
}
// When the control gets unloaded, unhook any remaining event handlers
// so that it can be garbage collected
private void OnUnloaded(object sender, RoutedEventArgs e) {
PropertyEntry entry = this.PropertyEntry;
if (entry != null)
DisassociatePropertyEventHandlers(entry);
}
// When the control gets re-loaded, re-hook any previous event handlers
// that may have been disassociated during Unload
private void OnLoaded(object sender, RoutedEventArgs e) {
PropertyEntry entry = this.PropertyEntry;
if (entry != null)
AssociatePropertyEventHandlers(entry);
}
// Helper that hooks into PropertyChanged events on the given Property
private void AssociatePropertyEventHandlers(PropertyEntry property) {
if (!_attachedToPropertyEntryEvents) {
property.PropertyChanged += new PropertyChangedEventHandler(OnPropertyPropertyChanged);
_attachedToPropertyEntryEvents = true;
}
}
// Helper that unhooks from PropertyChanged events on the given Property
private void DisassociatePropertyEventHandlers(PropertyEntry property) {
if (_attachedToPropertyEntryEvents) {
property.PropertyChanged -= new PropertyChangedEventHandler(OnPropertyPropertyChanged);
_attachedToPropertyEntryEvents = false;
}
}
// Called when the properties of the Property object change
private void OnPropertyPropertyChanged(object sender, PropertyChangedEventArgs e) {
// Propagate MatchesFilter change notifications outwards so that
// people can set up triggers against it
if ("MatchesFilter".Equals(e.PropertyName))
this.OnPropertyChanged("MatchesFilter");
else if ("PropertyValueEditor".Equals(e.PropertyName))
this.NotifyTemplatesChanged();
}
///
/// Helper class that attempts to find the DataTemplate for the requested PropertyContainerEditMode
/// given the currently displayed PropertyEntry and the currently set default PropertyValueEditors.
///
/// If the requested DataTemplate is found on the PropertyValueEditor associated with the displayed
/// control, is it returned.
///
/// Otherwise if the requested DataTemplate is found on DefaultStandardValuesPropertyValueEditor,
/// it is returned.
///
/// Otherwise if the requested DataTemplate is found on DefaultPropertyValueEditor,
/// it is returned.
///
/// Otherwise null is returned.
///
/// The editMode for which the DataTemplate should be retrieved
/// Most relevant DataTemplate for the specified edit mode based on the currently
/// displayed PropertyEntry and the current set of default PropertyValueEditors, or null if not
/// found.
private DataTemplate FindPropertyValueEditorTemplate(PropertyContainerEditMode editMode) {
PropertyEntry property = this.PropertyEntry;
PropertyValueEditor editor = null;
DataTemplate requestedTemplate = null;
// Look at property
if (property != null) {
editor = property.PropertyValueEditor;
if (editor != null) {
requestedTemplate = editor.GetPropertyValueEditor(editMode);
}
}
if (requestedTemplate != null)
return requestedTemplate;
// Is the property of type enum and used as flags?
if (IsFlagsProperty(property))
{
requestedTemplate = this.GetFlagEditorTemplate(editMode);
}
if (requestedTemplate != null)
{
return requestedTemplate;
}
// Does the property have standard values?
if (property != null && property.HasStandardValuesInternal) {
editor = this.DefaultStandardValuesPropertyValueEditor;
if (editor != null) {
requestedTemplate = editor.GetPropertyValueEditor(editMode);
}
}
if (requestedTemplate != null)
return requestedTemplate;
// Use the default
editor = this.DefaultPropertyValueEditor;
if (editor != null) {
requestedTemplate = editor.GetPropertyValueEditor(editMode);
}
return requestedTemplate;
}
bool IsFlagsProperty(PropertyEntry property)
{
return property != null && property.PropertyType != null && property.PropertyType.IsEnum &&
ExtensibilityAccessor.GetAttribute(property.PropertyType) != null;
}
DataTemplate GetFlagEditorTemplate(PropertyContainerEditMode editMode)
{
Type propertyType = this.PropertyEntry.PropertyType;
if (editMode == PropertyContainerEditMode.Inline)
{
if(this.flagEditorTemplate == null)
{
this.flagEditorTemplate = new DataTemplate();
this.flagEditorTemplate.VisualTree = new FrameworkElementFactory(typeof(FlagEditor));
this.flagEditorTemplate.VisualTree.SetValue(FlagEditor.FlagTypeProperty, propertyType);
Binding binding = new Binding("Value");
binding.Converter = new FlagStringConverter();
binding.ConverterParameter = propertyType;
binding.UpdateSourceTrigger = UpdateSourceTrigger.Explicit;
this.flagEditorTemplate.VisualTree.SetBinding(FlagEditor.TextProperty, binding);
}
return this.flagEditorTemplate;
}
else
{
return null;
}
}
// Helper that tries to find the first applicable DialogPropertyValueEditor
private DialogPropertyValueEditor FindDialogPropertyValueEditor() {
PropertyEntry property = this.PropertyEntry;
DialogPropertyValueEditor editor = null;
// Look at property
if (property != null) {
editor = property.PropertyValueEditor as DialogPropertyValueEditor;
}
if (editor != null)
return editor;
// Does the property have standard values?
if (property != null && property.HasStandardValuesInternal) {
editor = this.DefaultStandardValuesPropertyValueEditor as DialogPropertyValueEditor;
}
if (editor != null)
return editor;
// Use the default
editor = this.DefaultPropertyValueEditor as DialogPropertyValueEditor;
return editor;
}
// Updates the ControlTemplate of this control based on the currently ActiveEditMode
private static void UpdateControlTemplate(PropertyContainer container) {
PropertyContainerEditMode editMode = container.ActiveEditMode;
ControlTemplate newTemplate = null;
switch (editMode) {
case PropertyContainerEditMode.Inline:
newTemplate = container.InlineRowTemplate;
break;
case PropertyContainerEditMode.ExtendedPopup:
newTemplate = container.ExtendedPopupRowTemplate;
break;
case PropertyContainerEditMode.ExtendedPinned:
newTemplate = container.ExtendedPinnedRowTemplate;
break;
case PropertyContainerEditMode.Dialog:
// In dialog case, just keep the same value
return;
default:
Debug.Fail(
string.Format(
System.Globalization.CultureInfo.CurrentCulture,
"PropertyContainerEditMode does not yet support PropertyContainerEditMode '{0}'.",
editMode.ToString()));
newTemplate = container.Template;
break;
}
if (newTemplate != container.Template)
container.Template = newTemplate;
}
private void NotifyTemplatesChanged() {
OnPropertyChanged("InlineEditorTemplate");
OnPropertyChanged("ExtendedEditorTemplate");
OnPropertyChanged("DialogEditorTemplate");
}
///
/// Called when a property changes
///
/// Name of the property
protected virtual void OnPropertyChanged(string propertyName) {
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
///
/// Called when a property changes
///
/// Name of the property
protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e) {
if (DependencyPropertyChanged != null)
DependencyPropertyChanged(this, e);
base.OnPropertyChanged(e);
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- TextEditorCopyPaste.cs
- WindowsToolbarAsMenu.cs
- Expander.cs
- XsdValidatingReader.cs
- ConnectionInterfaceCollection.cs
- TagPrefixCollection.cs
- Overlapped.cs
- DomainUpDown.cs
- ConfigurationStrings.cs
- SmtpCommands.cs
- PropertyDescriptorCollection.cs
- Baml2006SchemaContext.cs
- LayoutManager.cs
- InvokePatternIdentifiers.cs
- CheckBoxField.cs
- Win32.cs
- ZipIOBlockManager.cs
- CapabilitiesPattern.cs
- QueryNode.cs
- Base64Stream.cs
- ErrorWebPart.cs
- LayoutTable.cs
- UnsafeNativeMethods.cs
- ObjectFullSpanRewriter.cs
- ColumnWidthChangedEvent.cs
- MetadataProperty.cs
- WorkflowValidationFailedException.cs
- CodeVariableReferenceExpression.cs
- BitmapDownload.cs
- PreviousTrackingServiceAttribute.cs
- RelatedEnd.cs
- ContractMapping.cs
- PrincipalPermission.cs
- ExcCanonicalXml.cs
- LoginUtil.cs
- FixedSOMTableCell.cs
- XmlQueryStaticData.cs
- Quaternion.cs
- XmlRawWriter.cs
- UserPersonalizationStateInfo.cs
- Attributes.cs
- PageCopyCount.cs
- Help.cs
- ProjectionPlanCompiler.cs
- BaseResourcesBuildProvider.cs
- XPathExpr.cs
- HostedTransportConfigurationManager.cs
- ConfigPathUtility.cs
- ConfigXmlText.cs
- MetadataFile.cs
- SamlAuthenticationClaimResource.cs
- DataGridViewCellValidatingEventArgs.cs
- CaseInsensitiveComparer.cs
- AmbientProperties.cs
- DataGridViewSelectedCellsAccessibleObject.cs
- CrossSiteScriptingValidation.cs
- StrokeDescriptor.cs
- MatrixTransform3D.cs
- SoapHeaders.cs
- InkCanvasFeedbackAdorner.cs
- OpacityConverter.cs
- CompleteWizardStep.cs
- BufferedWebEventProvider.cs
- MethodBuilder.cs
- ChildTable.cs
- xml.cs
- ComponentChangingEvent.cs
- SqlUtil.cs
- FileNotFoundException.cs
- FileEnumerator.cs
- StdValidatorsAndConverters.cs
- ItemCollectionEditor.cs
- MeshGeometry3D.cs
- ControlIdConverter.cs
- SlotInfo.cs
- BitmapImage.cs
- QueryTreeBuilder.cs
- Propagator.Evaluator.cs
- WebPartConnectionsEventArgs.cs
- MenuAdapter.cs
- OdbcUtils.cs
- WpfXamlLoader.cs
- ConfigXmlSignificantWhitespace.cs
- UniqueConstraint.cs
- HttpPostedFile.cs
- CfgSemanticTag.cs
- TableItemStyle.cs
- BuildResultCache.cs
- SelectingProviderEventArgs.cs
- FixedSOMLineRanges.cs
- FormsAuthentication.cs
- PersonalizationDictionary.cs
- DefaultMemberAttribute.cs
- XPathNavigatorKeyComparer.cs
- SafeViewOfFileHandle.cs
- WebProxyScriptElement.cs
- MimeTypeMapper.cs
- AdornerPresentationContext.cs
- SafeMILHandle.cs
- BinaryObjectReader.cs