using System;
using System.Collections.Generic;
using System.ComponentModel;
namespace DynamicDescriptors;
///
/// A runtime-customizable implementation of .
///
public sealed class DynamicPropertyDescriptor : PropertyDescriptor
{
///
/// The on which this is based.
///
private readonly PropertyDescriptor _descriptor;
///
/// A dictionary mapping editor base types to editor instances.
///
private readonly IDictionary _editorDictionary;
///
/// Gets or sets a value indicating whether the dynamic property descriptor is active.
/// If not, it won't be returned by the
/// or methods.
///
private bool _active;
///
/// If this value is not null, it will be returned by the Category property;
/// otherwise, the base descriptor's Category property will be returned.
///
private string _categoryOverride;
///
/// If this value is not null, it will be returned by the Converter property;
/// otherwise, the base descriptor's Converter property will be returned.
///
private TypeConverter _converterOverride;
///
/// If this value is not null, it will be returned by the Description property;
/// otherwise, the base descriptor's Description property will be returned.
///
private string _descriptionOverride;
///
/// If this value is not null, it will be returned by the DisplayName property;
/// otherwise, the base descriptor's DisplayName property will be returned.
///
private string _displayNameOverride;
///
/// If this value is not null, it will be returned by the IsReadOnly property;
/// otherwise, the base descriptor's IsReadOnly property will be returned.
///
private bool? _isReadOnlyOverride;
///
/// The order in which this property will be retrieved from its type descriptor.
///
private int? _propertyOrder;
///
/// Initializes a new instance of the class.
///
///
/// The on which this will be based.
///
public DynamicPropertyDescriptor(PropertyDescriptor descriptor)
: base(Preconditions.CheckNotNull(descriptor, nameof(descriptor)))
{
_descriptor = descriptor;
_editorDictionary = new Dictionary();
_active = true;
}
///
/// Gets or sets a value indicating whether the dynamic property descriptor is active.
/// If not, it won't be returned by the
/// or methods.
///
public bool Active
{
get => _active;
set => _active = value;
}
///
/// Returns a value indicating whether resetting an object changes its value.
///
/// The component to test for reset capability.
/// true if resetting the component changes its value; otherwise, false.
public override bool CanResetValue(object component)
{
return _descriptor.CanResetValue(component);
}
///
/// Gets the name of the category to which the member belongs,
/// as specified in the .
///
public override string Category => _categoryOverride ?? _descriptor.Category;
///
/// Gets the type of the component this property is bound to.
///
public override Type ComponentType => _descriptor.ComponentType;
///
/// Gets the type converter for this property.
///
public override TypeConverter Converter => _converterOverride ?? _descriptor.Converter;
///
/// Gets the description of the member,
/// as specified in the .
///
public override string Description => _descriptionOverride ?? _descriptor.Description;
///
/// Gets the name that can be displayed in a window, such as a Properties window.
///
public override string DisplayName => _displayNameOverride ?? _descriptor.DisplayName;
///
/// Gets an editor of the specified type.
///
///
/// The base type of editor, which is used to differentiate between multiple
/// editors that a property supports.
///
///
/// An instance of the requested editor type, or null if an editor cannot be found.
///
public override object GetEditor(Type editorBaseType)
{
if (editorBaseType != null)
{
if (_editorDictionary.TryGetValue(editorBaseType, out var editor))
{
return editor;
}
}
return _descriptor.GetEditor(editorBaseType);
}
///
/// Returns the current value of the property on a component.
///
///
/// The component with the property for which to retrieve the value.
///
/// The value of a property for a given component.
public override object GetValue(object component)
{
return _descriptor.GetValue(component);
}
///
/// Gets a value indicating whether this property is read-only.
///
public override bool IsReadOnly => _isReadOnlyOverride ?? _descriptor.IsReadOnly;
///
/// Gets the order in which this property will be retrieved from its type descriptor.
///
public int? PropertyOrder => _propertyOrder;
///
/// Gets the type of the property.
///
public override Type PropertyType => _descriptor.PropertyType;
///
/// Resets the value for this property of the component to the default value.
///
///
/// The component with the property value that is to be reset to the default value.
///
public override void ResetValue(object component)
{
_descriptor.ResetValue(component);
OnValueChanged(component, EventArgs.Empty);
}
///
/// Sets the value of the component to a different value.
///
///
/// The component with the property value that is to be set.
///
///
/// The new value.
///
public override void SetValue(object component, object value)
{
_descriptor.SetValue(component, value);
OnValueChanged(component, EventArgs.Empty);
}
///
/// Determines a value indicating whether the value of this property needs to be persisted.
///
///
/// The component with the property to be examined for persistence.
///
/// true if the property should be persisted; otherwise, false.
public override bool ShouldSerializeValue(object component)
{
return _descriptor.ShouldSerializeValue(component);
}
#region Fluent interface
///
/// Sets value that determines whether the dynamic property descriptor is active.
///
///
/// The value that determines whether the dynamic property descriptor is active.
///
/// This instance.
public DynamicPropertyDescriptor SetActive(bool active)
{
_active = active;
return this;
}
///
/// Sets the override for the property.
///
/// The new value for the property.
/// This instance.
public DynamicPropertyDescriptor SetCategory(string category)
{
_categoryOverride = category;
return this;
}
///
/// Sets the override for the property.
///
/// The new value for the property.
/// This instance.
public DynamicPropertyDescriptor SetConverter(TypeConverter converter)
{
_converterOverride = converter;
return this;
}
///
/// Sets the override for the property.
///
/// The new value for the property.
/// This instance.
public DynamicPropertyDescriptor SetDescription(string description)
{
_descriptionOverride = description;
return this;
}
///
/// Sets the override for the property.
///
/// The new value for the property.
/// This instance.
public DynamicPropertyDescriptor SetDisplayName(string displayName)
{
_displayNameOverride = displayName;
return this;
}
///
/// Sets the editor for this type.
///
///
/// The base type of editor, which is used to differentiate between multiple editors
/// that a property supports.
///
///
/// An instance of the requested editor type.
///
/// This instance.
public DynamicPropertyDescriptor SetEditor(Type editorBaseType, object editor)
{
if (editorBaseType != null)
{
if (_editorDictionary.ContainsKey(editorBaseType))
{
if (editor == null)
{
_editorDictionary.Remove(editorBaseType);
}
else
{
_editorDictionary[editorBaseType] = editor;
}
}
else
{
if (editor != null)
{
_editorDictionary.Add(editorBaseType, editor);
}
}
}
return this;
}
///
/// Sets the order in which this property will be retrieved from its type descriptor.
///
/// The order in which this property will be retrieved.
/// This instance.
public DynamicPropertyDescriptor SetPropertyOrder(int? propertyOrder)
{
_propertyOrder = propertyOrder;
return this;
}
///
/// Sets the override for the property.
///
/// The new value for the property.
/// This instance.
public DynamicPropertyDescriptor SetReadOnly(bool? readOnly)
{
_isReadOnlyOverride = readOnly;
return this;
}
#endregion
}