|
//-------------------------------------------------------------
// <copyright company=’Microsoft Corporation’>
// Copyright © Microsoft Corporation. All Rights Reserved.
// </copyright>
//-------------------------------------------------------------
// @owner=alexgor, deliant
//=================================================================
// File: CustomattributesConverter.cs
//
// Namespace: DataVisualization.Charting.Design
//
// Interfaces: IDataPointCustomPropertiesProvider
//
// Classes: CustomPropertiesTypeConverter, DynamicPropertyDescriptor
//
// Purpose: AxisName converter of the design-time CustomProperties
// property object.
//
// Reviewed:
//
//===================================================================
#region Used Namespaces
using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Globalization;
using System.Diagnostics.CodeAnalysis;
#if Microsoft_CONTROL
using System.Windows.Forms.DataVisualization.Charting.Utilities;
using System.Windows.Forms.DataVisualization.Charting;
#else
using System.Web.UI.DataVisualization.Charting.Utilities;
using System.Web.UI.DataVisualization.Charting;
#endif
#endregion
#if Microsoft_CONTROL
namespace System.Windows.Forms.DataVisualization.Charting
#else
namespace System.Web.UI.DataVisualization.Charting
#endif
{
/// <summary>
/// Custom properties object type converter.
/// </summary>
internal class CustomPropertiesTypeConverter : TypeConverter
{
#region String to/from convertion methods
/// <summary>
/// Overrides the CanConvertFrom method of TypeConverter.
/// </summary>
/// <param name="context">Descriptor context.</param>
/// <param name="sourceType">Convertion source type.</param>
/// <returns>Indicates if convertion is possible.</returns>
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
if(sourceType == typeof(string))
{
return true;
}
return base.CanConvertFrom(context, sourceType);
}
/// <summary>
/// Overrides the CanConvertTo method of TypeConverter.
/// </summary>
/// <param name="context">Descriptor context.</param>
/// <param name="destinationType">Destination type.</param>
/// <returns>Indicates if convertion is possible.</returns>
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
if(destinationType == typeof(CustomProperties))
{
return true;
}
return base.CanConvertTo(context, destinationType);
}
/// <summary>
/// Overrides the ConvertTo method of TypeConverter.
/// </summary>
/// <param name="context">Descriptor context.</param>
/// <param name="culture">Culture information.</param>
/// <param name="value">Value to convert.</param>
/// <param name="destinationType">Convertion destination type.</param>
/// <returns>Converted object.</returns>
public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
{
if (destinationType == typeof(string))
{
return ((CustomProperties)value).DataPointCustomProperties.CustomProperties;
}
return base.ConvertTo(context, culture, value, destinationType);
}
/// <summary>
/// Overrides the ConvertFrom method of TypeConverter.
/// Converts from string with comma separated values.
/// </summary>
/// <param name="context">Descriptor context.</param>
/// <param name="culture">Culture information.</param>
/// <param name="value">Value to convert from.</param>
/// <returns>Indicates if convertion is possible.</returns>
[SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily",
Justification = "Too large of a code change to justify making this change")]
public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
{
string stringValue = value as string;
if(stringValue != null && context != null && context.Instance != null)
{
// Create new custom attribute class with a reference to the DataPointCustomProperties
if(context.Instance is DataPointCustomProperties)
{
((DataPointCustomProperties)context.Instance).CustomProperties = stringValue;
CustomProperties newAttributes = new CustomProperties(((DataPointCustomProperties)context.Instance));
return newAttributes;
}
else if (context.Instance is CustomProperties)
{
CustomProperties newAttributes = new CustomProperties(((CustomProperties)context.Instance).DataPointCustomProperties);
return newAttributes;
}
else if (context.Instance is IDataPointCustomPropertiesProvider)
{
CustomProperties newAttributes = new CustomProperties(((IDataPointCustomPropertiesProvider)context.Instance).DataPointCustomProperties);
return newAttributes;
}
else if (context.Instance is Array)
{
DataPointCustomProperties attributes = null;
foreach (object obj in ((Array)context.Instance))
{
if (obj is DataPointCustomProperties)
{
attributes = (DataPointCustomProperties)obj;
attributes.CustomProperties = stringValue;
}
}
if (attributes != null)
{
CustomProperties newAttributes = new CustomProperties(attributes);
return newAttributes;
}
}
}
return base.ConvertFrom(context, culture, value);
}
#endregion // String to/from convertion methods
#region Property Descriptor Collection methods
/// <summary>
/// Returns whether this object supports properties.
/// </summary>
/// <param name="context">An ITypeDescriptorContext that provides a format context.</param>
/// <returns>true if GetProperties should be called to find the properties of this object; otherwise, false.</returns>
public override bool GetPropertiesSupported(ITypeDescriptorContext context)
{
return true;
}
/// <summary>
/// Returns a collection of properties for the type of array specified by the value parameter,
/// using the specified context and properties.
/// </summary>
/// <param name="context">An ITypeDescriptorContext that provides a format context.</param>
/// <param name="obj">An Object that specifies the type of array for which to get properties.</param>
/// <param name="attributes">An array of type Attribute that is used as a filter.</param>
/// <returns>A PropertyDescriptorCollection with the properties that are exposed for this data type, or a null reference (Nothing in Visual Basic) if there are no properties.</returns>
public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object obj, Attribute[] attributes)
{
PropertyDescriptorCollection propCollection = new PropertyDescriptorCollection(null);
CustomProperties attr = obj as CustomProperties;
if(attr != null && context != null)
{
// Get series associated with custom attribute
Series series = (attr.DataPointCustomProperties is Series) ? ( (Series) attr.DataPointCustomProperties) : attr.DataPointCustomProperties.series;
if(series != null &&
series.Common != null)
{
// Loop through all registered custom properties
CustomPropertyRegistry registry = (CustomPropertyRegistry)series.Common.container.GetService(typeof(CustomPropertyRegistry));
foreach(CustomPropertyInfo attrInfo in registry.registeredCustomProperties)
{
// Check if attribute description matches curent selection in property browser
if(IsApplicableCustomProperty(attrInfo, context.Instance))
{
// Get array of property properties
Attribute[] propAttributes = GetPropertyAttributes(attrInfo);
// Create property descriptor
CustomAttributesPropertyDescriptor propertyDescriptor = new CustomAttributesPropertyDescriptor(
typeof(CustomProperties),
attrInfo.Name,
attrInfo.ValueType,
propAttributes,
attrInfo);
// Add descriptor into the collection
propCollection.Add(propertyDescriptor);
}
}
// Always add "UserDefined" property for all user defined custom properties
Attribute[] propUserDefinedAttributes = new Attribute[] {
new NotifyParentPropertyAttribute(true),
new RefreshPropertiesAttribute(RefreshProperties.All),
new DescriptionAttribute(SR.DescriptionAttributeUserDefined)
};
// Create property descriptor
CustomAttributesPropertyDescriptor propertyUserDefinedDescriptor = new CustomAttributesPropertyDescriptor(
typeof(CustomProperties),
"UserDefined",
typeof(string),
propUserDefinedAttributes,
null);
// Add descriptor into the collection
propCollection.Add(propertyUserDefinedDescriptor);
}
}
return propCollection;
}
/// <summary>
/// Checks if provided custom attribute appies to the selected points or series.
/// </summary>
/// <param name="attrInfo">Custom attribute information.</param>
/// <param name="obj">Selected series or points.</param>
/// <returns>True if custom attribute applies.</returns>
private bool IsApplicableCustomProperty(CustomPropertyInfo attrInfo, object obj)
{
CustomProperties customProperties = obj as CustomProperties;
if (customProperties != null)
{
obj = customProperties.DataPointCustomProperties;
}
// Check if custom attribute applies to the series or points
if( (IsDataPoint(obj) && attrInfo.AppliesToDataPoint) ||
(!IsDataPoint(obj) && attrInfo.AppliesToSeries) )
{
// Check if attribute do not apply to 3D or 2D chart types
if( (Is3DChartType(obj) && attrInfo.AppliesTo3D) ||
(!Is3DChartType(obj) && attrInfo.AppliesTo2D) )
{
// Check if custom attribute applies to the chart types selected
SeriesChartType[] chartTypes = GetSelectedChartTypes(obj);
foreach(SeriesChartType chartType in chartTypes)
{
foreach(SeriesChartType attrChartType in attrInfo.AppliesToChartType)
{
if(attrChartType == chartType)
{
return true;
}
}
}
}
}
return false;
}
/// <summary>
/// Checks if specified object represent a single or array of data points.
/// </summary>
/// <param name="obj">Object to test.</param>
/// <returns>True if specified object contains one or more data points.</returns>
private bool IsDataPoint(object obj)
{
Series series = obj as Series;
if(series != null)
{
return false;
}
Array array = obj as Array;
if(array != null && array.Length > 0)
{
if (array.GetValue(0) is Series)
{
return false;
}
}
return true;
}
/// <summary>
/// Checks if specified object represent a single or array of data points.
/// </summary>
/// <param name="obj">Object to test.</param>
/// <returns>True if specified object contains one or more data points.</returns>
private bool Is3DChartType(object obj)
{
// Get array of series
Series[] seriesArray = GetSelectedSeries(obj);
// Loop through all series and check if its plotted on 3D chart area
foreach(Series series in seriesArray)
{
ChartArea chartArea = series.Chart.ChartAreas[series.ChartArea];
if(chartArea.Area3DStyle.Enable3D)
{
return true;
}
}
return false;
}
/// <summary>
/// Get array of selected series.
/// </summary>
/// <param name="obj">Selected objects.</param>
/// <returns>Selected series array.</returns>
[SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily",
Justification = "Too large of a code change to justify making this change")]
private Series[] GetSelectedSeries(object obj)
{
// Get array of series
Series[] seriesArray = new Series[0];
if(obj is Array && ((Array)obj).Length > 0)
{
if(((Array)obj).GetValue(0) is Series)
{
seriesArray = new Series[((Array)obj).Length];
((Array)obj).CopyTo(seriesArray, 0);
}
else if(((Array)obj).GetValue(0) is DataPointCustomProperties)
{
seriesArray = new Series[] { ((DataPointCustomProperties)((Array)obj).GetValue(0)).series };
}
}
else if(obj is Series)
{
seriesArray = new Series[] { ((Series)obj) };
}
else if(obj is DataPointCustomProperties)
{
seriesArray = new Series[] { ((DataPointCustomProperties)obj).series };
}
return seriesArray;
}
/// <summary>
/// Get array of chart types from the selected series.
/// </summary>
/// <param name="obj">Selected series or data points.</param>
/// <returns>Array of selected chart types.</returns>
private SeriesChartType[] GetSelectedChartTypes(object obj)
{
// Get array of series
Series[] seriesArray = GetSelectedSeries(obj);
// Create array of chart types
int index = 0;
SeriesChartType[] chartTypes = new SeriesChartType[seriesArray.Length];
foreach(Series series in seriesArray)
{
chartTypes[index++] = series.ChartType;
}
return chartTypes;
}
/// <summary>
/// Gets array of properties for the dynamic property.
/// </summary>
/// <param name="attrInfo">Custom attribute information.</param>
/// <returns>Array of properties.</returns>
private Attribute[] GetPropertyAttributes(CustomPropertyInfo attrInfo)
{
// Create default value attribute
DefaultValueAttribute defaultValueAttribute = null;
if (attrInfo.DefaultValue.GetType() == attrInfo.ValueType)
{
defaultValueAttribute = new DefaultValueAttribute(attrInfo.DefaultValue);
}
else if (attrInfo.DefaultValue is string)
{
defaultValueAttribute = new DefaultValueAttribute(attrInfo.ValueType, (string)attrInfo.DefaultValue);
}
else
{
throw (new InvalidOperationException(SR.ExceptionCustomAttributeDefaultValueTypeInvalid));
}
// Add all properties into the list
ArrayList propList = new ArrayList();
propList.Add(new NotifyParentPropertyAttribute(true));
propList.Add(new RefreshPropertiesAttribute(RefreshProperties.All));
propList.Add(new DescriptionAttribute(attrInfo.Description));
propList.Add(defaultValueAttribute);
if (attrInfo.Name.Equals(CustomPropertyName.ErrorBarType, StringComparison.Ordinal))
{
propList.Add(new TypeConverterAttribute(typeof(ErrorBarTypeConverter)));
}
// Convert list to array
int index = 0;
Attribute[] propAttributes = new Attribute[propList.Count];
foreach(Attribute attr in propList)
{
propAttributes[index++] = attr;
}
return propAttributes;
}
/// <summary>
/// Special convertor for ErrorBarType custom attribute
/// </summary>
internal class ErrorBarTypeConverter : StringConverter
{
/// <summary>
/// Returns whether this object supports a standard set of values that can be picked from a list, using the specified context.
/// </summary>
/// <param name="context">An <see cref="T:System.ComponentModel.ITypeDescriptorContext"/> that provides a format context.</param>
/// <returns>
/// true if <see cref="M:System.ComponentModel.TypeConverter.GetStandardValues"/> should be called to find a common set of values the object supports; otherwise, false.
/// </returns>
public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
{
return true;
}
/// <summary>
/// Returns whether the collection of standard values returned from <see cref="M:System.ComponentModel.TypeConverter.GetStandardValues"/> is an exclusive list of possible values, using the specified context.
/// </summary>
/// <param name="context">An <see cref="T:System.ComponentModel.ITypeDescriptorContext"/> that provides a format context.</param>
/// <returns>
/// true if the <see cref="T:System.ComponentModel.TypeConverter.StandardValuesCollection"/> returned from <see cref="M:System.ComponentModel.TypeConverter.GetStandardValues"/> is an exhaustive list of possible values; false if other values are possible.
/// </returns>
public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
{
return false;
}
/// <summary>
/// Returns a collection of standard values for the data type this type converter is designed for when provided with a format context.
/// </summary>
/// <param name="context">An <see cref="T:System.ComponentModel.ITypeDescriptorContext"/> that provides a format context that can be used to extract additional information about the environment from which this converter is invoked. This parameter or properties of this parameter can be null.</param>
/// <returns>
/// A <see cref="T:System.ComponentModel.TypeConverter.StandardValuesCollection"/> that holds a standard set of valid values, or null if the data type does not support a standard set of values.
/// </returns>
public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
{
ArrayList result = new ArrayList();
foreach (ChartTypes.ErrorBarType item in Enum.GetValues(typeof(ChartTypes.ErrorBarType)))
{
string itemStr = String.Format(CultureInfo.InvariantCulture, "{0}({1:N0})", item, ChartTypes.ErrorBarChart.DefaultErrorBarTypeValue(item));
result.Add(itemStr);
}
return new StandardValuesCollection(result);
}
}
#endregion // Property Descriptor Collection methods
#region Custom Attributes Property Descriptor
/// <summary>
/// Custom properties inner property descriptor class.
/// </summary>
protected class CustomAttributesPropertyDescriptor : TypeConverter.SimplePropertyDescriptor
{
#region Fields
// Property name
private string _name = string.Empty;
// Custom attribute information
private CustomPropertyInfo _customAttributeInfo = null;
#endregion // Fields
#region Constructor
/// <summary>
/// Property descriptor constructor.
/// </summary>
/// <param name="componentType">Component type.</param>
/// <param name="name">Property name.</param>
/// <param name="propertyType">Property type.</param>
/// <param name="attributes">Property attributes.</param>
/// <param name="customAttributeInfo">Custom attribute information.</param>
internal CustomAttributesPropertyDescriptor(
Type componentType,
string name,
Type propertyType,
Attribute[] attributes,
CustomPropertyInfo customAttributeInfo)
: base(componentType, name, propertyType, attributes)
{
this._name = name;
this._customAttributeInfo = customAttributeInfo;
}
#endregion // Constructor
#region Methods
/// <summary>
/// Gets the current value of the property on a component.
/// </summary>
/// <param name="component">The component with the property for which to retrieve the value.</param>
/// <returns>The value of a property for a given component.</returns>
public override object GetValue(object component)
{
// "UserDefined" property expose comma separated user defined properties
CustomProperties customAttr = component as CustomProperties;
if(this._name == "UserDefined")
{
return customAttr.GetUserDefinedCustomProperties();
}
else
{
object val = null;
// Check if custom attribute with this name is set
string stringValue = customAttr.DataPointCustomProperties[this._name];
if(this._customAttributeInfo != null)
{
if(stringValue == null || stringValue.Length == 0)
{
val = GetValueFromString(this._customAttributeInfo.DefaultValue);
}
else
{
val = GetValueFromString(stringValue);
}
}
else
{
val = stringValue;
}
return val;
}
}
/// <summary>
/// Sets the value of the component to a different value.
/// </summary>
/// <param name="component">The component with the property value that is to be set.</param>
/// <param name="value">The new value.</param>
public override void SetValue(object component, object value)
{
// Validate new value
ValidateValue(this._name, value);
// Get new value as string
string stringValue = GetStringFromValue(value);
// "UserDefined" property expose comma separated user defined properties
CustomProperties customAttr = component as CustomProperties;
if( this._name == "UserDefined" )
{
customAttr.SetUserDefinedAttributes(stringValue);
}
else
{
// Check if the new value is the same as DefaultValue
bool setAttributeValue = true;
if( IsDefaultValue(stringValue) )
{
// Remove custom properties with default values from data point
// only when series do not have this attribute set.
if( !(customAttr.DataPointCustomProperties is DataPoint) ||
!((DataPoint)customAttr.DataPointCustomProperties).series.IsCustomPropertySet(this._name) )
{
// Delete attribute
if(customAttr.DataPointCustomProperties.IsCustomPropertySet(this._name))
{
customAttr.DataPointCustomProperties.DeleteCustomProperty(this._name);
setAttributeValue = false;
}
}
}
// Set custom attribute value
if( setAttributeValue )
{
customAttr.DataPointCustomProperties[this._name] = stringValue;
}
}
customAttr.DataPointCustomProperties.CustomProperties = customAttr.DataPointCustomProperties.CustomProperties;
IChangeTracking changeTracking = component as IChangeTracking;
if (changeTracking != null)
{
changeTracking.AcceptChanges();
}
}
/// <summary>
/// Checks if specified value is the default value of the attribute.
/// </summary>
/// <param name="val">Value to check.</param>
/// <returns>True if specified value is the default attribute value.</returns>
public bool IsDefaultValue(string val)
{
// Get default value string
string defaultValue = GetStringFromValue(this._customAttributeInfo.DefaultValue);
return (String.Compare(val, defaultValue, StringComparison.Ordinal) == 0);
}
/// <summary>
/// Gets value from string a native type of attribute.
/// </summary>
/// <param name="obj">Object to convert to string.</param>
/// <returns>String representation of the specified object.</returns>
public virtual object GetValueFromString(object obj)
{
object result = null;
if(obj != null)
{
if(this._customAttributeInfo.ValueType == obj.GetType() )
{
return obj;
}
string stringValue = obj as string;
if (stringValue != null)
{
if(this._customAttributeInfo.ValueType == typeof(string) )
{
result = stringValue;
}
else if(this._customAttributeInfo.ValueType == typeof(float) )
{
result = float.Parse(stringValue, System.Globalization.CultureInfo.InvariantCulture);
}
else if(this._customAttributeInfo.ValueType == typeof(double) )
{
result = double.Parse(stringValue, System.Globalization.CultureInfo.InvariantCulture);
}
else if(this._customAttributeInfo.ValueType == typeof(int) )
{
result = int.Parse(stringValue, System.Globalization.CultureInfo.InvariantCulture);
}
else if(this._customAttributeInfo.ValueType == typeof(bool) )
{
result = bool.Parse(stringValue);
}
else if(this._customAttributeInfo.ValueType == typeof(Color) )
{
ColorConverter colorConverter = new ColorConverter();
result = (Color)colorConverter.ConvertFromString(null, System.Globalization.CultureInfo.InvariantCulture, stringValue);
}
else if(this._customAttributeInfo.ValueType.IsEnum)
{
result = Enum.Parse(this._customAttributeInfo.ValueType, stringValue, true);
}
else
{
throw (new InvalidOperationException(SR.ExceptionCustomAttributeTypeUnsupported( this._customAttributeInfo.ValueType.ToString() )));
}
}
}
return result;
}
/// <summary>
/// Converts attribute value to string.
/// </summary>
/// <param name="value">Attribute value to convert.</param>
/// <returns>Return attribute value converted to string.</returns>
public string GetStringFromValue(object value)
{
if(value is Color)
{
ColorConverter colorConverter = new ColorConverter();
return colorConverter.ConvertToString(null, System.Globalization.CultureInfo.InvariantCulture, value);
}
else if(value is float)
{
return ((float)value).ToString(System.Globalization.CultureInfo.InvariantCulture);
}
else if(value is double)
{
return ((double)value).ToString(System.Globalization.CultureInfo.InvariantCulture);
}
else if(value is int)
{
return ((int)value).ToString(System.Globalization.CultureInfo.InvariantCulture);
}
else if(value is bool)
{
return ((bool)value).ToString();
}
return value.ToString();
}
/// <summary>
/// Validates attribute value. Method throws exception in case of any issues.
/// </summary>
/// <param name="attrName">Attribute name.</param>
/// <param name="value">Attribute value to validate.</param>
[SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily",
Justification = "Too large of a code change to justify making this change")]
public virtual void ValidateValue(string attrName, object value)
{
// Check for validation rules
if(this._customAttributeInfo == null)
{
return;
}
// Check if property Min/Max value is provided
bool outOfRange = false;
if(this._customAttributeInfo.MaxValue != null)
{
if(value.GetType() != this._customAttributeInfo.MaxValue.GetType())
{
throw(new InvalidOperationException(SR.ExceptionCustomAttributeTypeOrMaximumPossibleValueInvalid( attrName ) ) );
}
if(value is float)
{
if((float)value > (float)this._customAttributeInfo.MaxValue)
{
outOfRange = true;
}
}
else if(value is double)
{
if((double)value > (double)this._customAttributeInfo.MaxValue)
{
outOfRange = true;
}
}
else if(value is int)
{
if((int)value > (int)this._customAttributeInfo.MaxValue)
{
outOfRange = true;
}
}
else
{
throw (new InvalidOperationException(SR.ExceptionCustomAttributeTypeOrMinimumPossibleValueUnsupported(attrName)));
}
}
// Check if property Min value is provided
if(this._customAttributeInfo.MinValue != null)
{
if(value.GetType() != this._customAttributeInfo.MinValue.GetType())
{
throw (new InvalidOperationException(SR.ExceptionCustomAttributeTypeOrMinimumPossibleValueInvalid( attrName ) ) );
}
if(value is float)
{
if((float)value < (float)this._customAttributeInfo.MinValue)
{
outOfRange = true;
}
}
else if(value is double)
{
if((double)value < (double)this._customAttributeInfo.MinValue)
{
outOfRange = true;
}
}
else if(value is int)
{
if((int)value < (int)this._customAttributeInfo.MinValue)
{
outOfRange = true;
}
}
else
{
throw(new InvalidOperationException(SR.ExceptionCustomAttributeTypeOrMinimumPossibleValueUnsupported(attrName)));
}
}
// Value out of range exception
if(outOfRange)
{
if(this._customAttributeInfo.MaxValue != null && this._customAttributeInfo.MinValue != null)
{
throw(new InvalidOperationException(SR.ExceptionCustomAttributeMustBeInRange(attrName, this._customAttributeInfo.MinValue.ToString(),this._customAttributeInfo.MaxValue.ToString() )));
}
else if(this._customAttributeInfo.MinValue != null)
{
throw(new InvalidOperationException(SR.ExceptionCustomAttributeMustBeBiggerThenValue(attrName, this._customAttributeInfo.MinValue.ToString())));
}
else if(this._customAttributeInfo.MaxValue != null)
{
throw(new InvalidOperationException(SR.ExceptionCustomAttributeMustBeMoreThenValue(attrName, this._customAttributeInfo.MaxValue.ToString())));
}
}
}
#endregion // Methods
}
#endregion // Custom Attributes Property Descriptor
}
/// <summary>
/// Property descriptor with ability to dynamically change properties
/// of the base property descriptor object.
/// </summary>
internal class DynamicPropertyDescriptor : PropertyDescriptor
{
#region Fields
// Reference to the base property descriptor
private PropertyDescriptor _basePropertyDescriptor = null;
// Dynamic display name of the property
private string _displayName = string.Empty;
#endregion // Fields
#region Constructor
/// <summary>
/// Constructor of the dynamic property descriptor.
/// </summary>
/// <param name="basePropertyDescriptor">Base property descriptor.</param>
/// <param name="displayName">New display name of the property.</param>
public DynamicPropertyDescriptor(
PropertyDescriptor basePropertyDescriptor,
string displayName)
: base(basePropertyDescriptor)
{
this._displayName = displayName;
this._basePropertyDescriptor = basePropertyDescriptor;
}
#endregion // Constructor
#region Properties
/// <summary>
/// Gets the type of the component this property is bound to.
/// </summary>
public override Type ComponentType
{
get
{
return _basePropertyDescriptor.ComponentType;
}
}
/// <summary>
/// Gets the name that can be displayed in a window, such as a Properties window.
/// </summary>
public override string DisplayName
{
get
{
if(this._displayName.Length > 0)
{
return this._displayName;
}
return this._basePropertyDescriptor.DisplayName;
}
}
/// <summary>
/// Gets a value indicating whether this property is browsable.
/// </summary>
public override bool IsBrowsable
{
get
{
return this._basePropertyDescriptor.IsBrowsable;
}
}
/// <summary>
/// Gets a value indicating whether this property is read-only.
/// </summary>
public override bool IsReadOnly
{
get
{
return this._basePropertyDescriptor.IsReadOnly;
}
}
/// <summary>
/// Gets the type of the property.
/// </summary>
public override Type PropertyType
{
get
{
return this._basePropertyDescriptor.PropertyType;
}
}
#endregion // Properties
#region Methods
/// <summary>
/// Returns whether resetting an object changes its value.
/// </summary>
/// <param name="component">The component to test for reset capability.</param>
/// <returns>true if resetting the component changes its value; otherwise, false.</returns>
public override bool CanResetValue(object component)
{
return _basePropertyDescriptor.CanResetValue(component);
}
/// <summary>
/// Gets the current value of the property on a component.
/// </summary>
/// <param name="component">The component with the property for which to retrieve the value.</param>
/// <returns>The value of a property for a given component.</returns>
public override object GetValue(object component)
{
return this._basePropertyDescriptor.GetValue(component);
}
/// <summary>
/// Resets the value for this property of the component to the default value.
/// </summary>
/// <param name="component">The component with the property value that is to be reset to the default value.</param>
public override void ResetValue(object component)
{
this._basePropertyDescriptor.ResetValue(component);
}
/// <summary>
/// Determines a value indicating whether the value of this property needs to be persisted.
/// </summary>
/// <param name="component">The component with the property to be examined for persistence.</param>
/// <returns>True if the property should be persisted; otherwise, false.</returns>
public override bool ShouldSerializeValue(object component)
{
return this._basePropertyDescriptor.ShouldSerializeValue(component);
}
/// <summary>
/// Sets the value of the component to a different value.
/// </summary>
/// <param name="component">The component with the property value that is to be set.</param>
/// <param name="value">The new value.</param>
public override void SetValue(object component, object value)
{
this._basePropertyDescriptor.SetValue(component, value);
}
#endregion // Methods
}
internal interface IDataPointCustomPropertiesProvider
{
DataPointCustomProperties DataPointCustomProperties { get; }
}
}
|