|
|
|
@ -2,21 +2,15 @@ |
|
|
|
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|
|
|
|
|
|
|
using System; |
|
|
|
using System.Collections.Generic; |
|
|
|
using System.Linq; |
|
|
|
using System.Reactive.Subjects; |
|
|
|
using System.Reflection; |
|
|
|
using Perspex.Data; |
|
|
|
using Perspex.Utilities; |
|
|
|
|
|
|
|
namespace Perspex |
|
|
|
{ |
|
|
|
/// <summary>
|
|
|
|
/// A perspex property.
|
|
|
|
/// Base class for perspex property metadata.
|
|
|
|
/// </summary>
|
|
|
|
/// <remarks>
|
|
|
|
/// This class is analogous to DependencyProperty in WPF.
|
|
|
|
/// </remarks>
|
|
|
|
public class PerspexProperty : IEquatable<PerspexProperty> |
|
|
|
{ |
|
|
|
/// <summary>
|
|
|
|
@ -29,16 +23,6 @@ namespace Perspex |
|
|
|
/// </summary>
|
|
|
|
private static int s_nextId = 1; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// The default value provided when the property was first registered.
|
|
|
|
/// </summary>
|
|
|
|
private readonly object _defaultValue; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// The overridden default values for the property, by type.
|
|
|
|
/// </summary>
|
|
|
|
private readonly Dictionary<Type, object> _defaultValues; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Observable fired when this property changes on any <see cref="PerspexObject"/>.
|
|
|
|
/// </summary>
|
|
|
|
@ -49,11 +33,6 @@ namespace Perspex |
|
|
|
/// </summary>
|
|
|
|
private readonly Subject<PerspexPropertyChangedEventArgs> _changed; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// The validation functions for the property, by type.
|
|
|
|
/// </summary>
|
|
|
|
private readonly Dictionary<Type, Func<PerspexObject, object, object>> _validation; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Gets the ID of the property.
|
|
|
|
/// </summary>
|
|
|
|
@ -65,26 +44,18 @@ namespace Perspex |
|
|
|
/// <param name="name">The name of the property.</param>
|
|
|
|
/// <param name="valueType">The type of the property's value.</param>
|
|
|
|
/// <param name="ownerType">The type of the class that registers the property.</param>
|
|
|
|
/// <param name="defaultValue">The default value of the property.</param>
|
|
|
|
/// <param name="inherits">Whether the property inherits its value.</param>
|
|
|
|
/// <param name="defaultBindingMode">The default binding mode for the property.</param>
|
|
|
|
/// <param name="validate">A validation function.</param>
|
|
|
|
/// <param name="notifying">
|
|
|
|
/// A method that gets called before and after the property starts being notified on an
|
|
|
|
/// object; the bool argument will be true before and false afterwards. This callback is
|
|
|
|
/// intended to support IsDataContextChanging.
|
|
|
|
/// </param>
|
|
|
|
/// <param name="isAttached">Whether the property is an attached property.</param>
|
|
|
|
public PerspexProperty( |
|
|
|
protected PerspexProperty( |
|
|
|
string name, |
|
|
|
Type valueType, |
|
|
|
Type ownerType, |
|
|
|
object defaultValue, |
|
|
|
bool inherits = false, |
|
|
|
BindingMode defaultBindingMode = BindingMode.Default, |
|
|
|
Func<PerspexObject, object, object> validate = null, |
|
|
|
Action<PerspexObject, bool> notifying = null, |
|
|
|
bool isAttached = false) |
|
|
|
Action<PerspexObject, bool> notifying = null) |
|
|
|
{ |
|
|
|
Contract.Requires<ArgumentNullException>(name != null); |
|
|
|
Contract.Requires<ArgumentNullException>(valueType != null); |
|
|
|
@ -95,64 +66,15 @@ namespace Perspex |
|
|
|
throw new ArgumentException("'name' may not contain periods."); |
|
|
|
} |
|
|
|
|
|
|
|
_defaultValues = new Dictionary<Type, object>(); |
|
|
|
_initialized = new Subject<PerspexPropertyChangedEventArgs>(); |
|
|
|
_changed = new Subject<PerspexPropertyChangedEventArgs>(); |
|
|
|
_validation = new Dictionary<Type, Func<PerspexObject, object, object>>(); |
|
|
|
|
|
|
|
Name = name; |
|
|
|
PropertyType = valueType; |
|
|
|
OwnerType = ownerType; |
|
|
|
_defaultValue = defaultValue; |
|
|
|
Inherits = inherits; |
|
|
|
DefaultBindingMode = defaultBindingMode; |
|
|
|
IsAttached = isAttached; |
|
|
|
Notifying = notifying; |
|
|
|
_id = s_nextId++; |
|
|
|
|
|
|
|
if (validate != null) |
|
|
|
{ |
|
|
|
_validation.Add(ownerType, validate); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Initializes a new instance of the <see cref="PerspexProperty"/> class.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="name">The name of the property.</param>
|
|
|
|
/// <param name="valueType">The type of the property's value.</param>
|
|
|
|
/// <param name="ownerType">The type of the class that registers the property.</param>
|
|
|
|
/// <param name="getter">Gets the current value of the property.</param>
|
|
|
|
/// <param name="setter">Sets the value of the property.</param>
|
|
|
|
public PerspexProperty( |
|
|
|
string name, |
|
|
|
Type valueType, |
|
|
|
Type ownerType, |
|
|
|
Func<PerspexObject, object> getter, |
|
|
|
Action<PerspexObject, object> setter) |
|
|
|
{ |
|
|
|
Contract.Requires<ArgumentNullException>(name != null); |
|
|
|
Contract.Requires<ArgumentNullException>(valueType != null); |
|
|
|
Contract.Requires<ArgumentNullException>(ownerType != null); |
|
|
|
Contract.Requires<ArgumentNullException>(getter != null); |
|
|
|
|
|
|
|
if (name.Contains(".")) |
|
|
|
{ |
|
|
|
throw new ArgumentException("'name' may not contain periods."); |
|
|
|
} |
|
|
|
|
|
|
|
_defaultValues = new Dictionary<Type, object>(); |
|
|
|
_initialized = new Subject<PerspexPropertyChangedEventArgs>(); |
|
|
|
_changed = new Subject<PerspexPropertyChangedEventArgs>(); |
|
|
|
_validation = new Dictionary<Type, Func<PerspexObject, object, object>>(); |
|
|
|
|
|
|
|
Name = name; |
|
|
|
PropertyType = valueType; |
|
|
|
OwnerType = ownerType; |
|
|
|
Getter = getter; |
|
|
|
Setter = setter; |
|
|
|
IsDirect = true; |
|
|
|
_id = s_nextId++; |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
@ -171,117 +93,62 @@ namespace Perspex |
|
|
|
"This method cannot be called on direct PerspexProperties."); |
|
|
|
} |
|
|
|
|
|
|
|
_defaultValues = source._defaultValues; |
|
|
|
_initialized = source._initialized; |
|
|
|
_changed = source._changed; |
|
|
|
_validation = source._validation; |
|
|
|
|
|
|
|
Name = source.Name; |
|
|
|
PropertyType = source.PropertyType; |
|
|
|
OwnerType = ownerType; |
|
|
|
_defaultValue = source._defaultValue; |
|
|
|
Inherits = source.Inherits; |
|
|
|
DefaultBindingMode = source.DefaultBindingMode; |
|
|
|
IsAttached = false; |
|
|
|
Notifying = Notifying; |
|
|
|
_validation = source._validation; |
|
|
|
_id = source._id; |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Initializes a new instance of the <see cref="PerspexProperty"/> class.
|
|
|
|
/// Gets the name of the property.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="source">The direct property to copy.</param>
|
|
|
|
/// <param name="ownerType">The new owner type.</param>
|
|
|
|
/// <param name="getter">A new getter.</param>
|
|
|
|
/// <param name="setter">A new setter.</param>
|
|
|
|
protected PerspexProperty( |
|
|
|
PerspexProperty source, |
|
|
|
Type ownerType, |
|
|
|
Func<PerspexObject, object> getter, |
|
|
|
Action<PerspexObject, object> setter) |
|
|
|
{ |
|
|
|
Contract.Requires<ArgumentNullException>(source != null); |
|
|
|
Contract.Requires<ArgumentNullException>(ownerType != null); |
|
|
|
Contract.Requires<ArgumentNullException>(getter != null); |
|
|
|
|
|
|
|
if (!source.IsDirect) |
|
|
|
{ |
|
|
|
throw new InvalidOperationException( |
|
|
|
"This method can only be called on direct PerspexProperties."); |
|
|
|
} |
|
|
|
|
|
|
|
_defaultValues = source._defaultValues; |
|
|
|
_initialized = source._initialized; |
|
|
|
_changed = source._changed; |
|
|
|
_validation = source._validation; |
|
|
|
|
|
|
|
Name = source.Name; |
|
|
|
PropertyType = source.PropertyType; |
|
|
|
OwnerType = ownerType; |
|
|
|
Getter = getter; |
|
|
|
Setter = setter; |
|
|
|
IsDirect = true; |
|
|
|
_id = source._id; |
|
|
|
} |
|
|
|
public string Name { get; } |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Gets the name of the property.
|
|
|
|
/// Gets the full name of the property, wich includes the owner type in the case of
|
|
|
|
/// attached properties.
|
|
|
|
/// </summary>
|
|
|
|
/// <value>
|
|
|
|
/// The name of the property.
|
|
|
|
/// </value>
|
|
|
|
public string Name { get; } |
|
|
|
public virtual string FullName => Name; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Gets the type of the property's value.
|
|
|
|
/// </summary>
|
|
|
|
/// <value>
|
|
|
|
/// The type of the property's value.
|
|
|
|
/// </value>
|
|
|
|
public Type PropertyType { get; } |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Gets the type of the class that registers the property.
|
|
|
|
/// Gets the type of the class that registered the property.
|
|
|
|
/// </summary>
|
|
|
|
/// <value>
|
|
|
|
/// The type of the class that registers the property.
|
|
|
|
/// </value>
|
|
|
|
public Type OwnerType { get; } |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Gets a value indicating whether the property inherits its value.
|
|
|
|
/// </summary>
|
|
|
|
/// <value>
|
|
|
|
/// A value indicating whether the property inherits its value.
|
|
|
|
/// </value>
|
|
|
|
public bool Inherits { get; } |
|
|
|
public virtual bool Inherits => false; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Gets the default binding mode for the property.
|
|
|
|
/// </summary>
|
|
|
|
/// <value>
|
|
|
|
/// The default binding mode for the property.
|
|
|
|
/// </value>
|
|
|
|
public BindingMode DefaultBindingMode { get; } |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Gets a value indicating whether this is an attached property.
|
|
|
|
/// </summary>
|
|
|
|
/// <value>
|
|
|
|
/// A value indicating whether this is an attached property.
|
|
|
|
/// </value>
|
|
|
|
public bool IsAttached { get; } |
|
|
|
public virtual bool IsAttached => false; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Gets a value indicating whether this is a direct property.
|
|
|
|
/// </summary>
|
|
|
|
public bool IsDirect { get; } |
|
|
|
public virtual bool IsDirect => false; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Gets a value indicating whether this is a readonly property.
|
|
|
|
/// </summary>
|
|
|
|
public bool IsReadOnly => IsDirect && Setter == null; |
|
|
|
public virtual bool IsReadOnly => false; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Gets an observable that is fired when this property is initialized on a
|
|
|
|
@ -349,16 +216,6 @@ namespace Perspex |
|
|
|
}; |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Gets the getter function for direct properties.
|
|
|
|
/// </summary>
|
|
|
|
internal Func<PerspexObject, object> Getter { get; } |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Gets the etter function for direct properties.
|
|
|
|
/// </summary>
|
|
|
|
internal Action<PerspexObject, object> Setter { get; } |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Tests two <see cref="PerspexProperty"/>s for equality.
|
|
|
|
/// </summary>
|
|
|
|
@ -407,55 +264,26 @@ namespace Perspex |
|
|
|
/// object; the bool argument will be true before and false afterwards. This callback is
|
|
|
|
/// intended to support IsDataContextChanging.
|
|
|
|
/// </param>
|
|
|
|
/// <returns>A <see cref="PerspexProperty{TValue}"/></returns>
|
|
|
|
public static PerspexProperty<TValue> Register<TOwner, TValue>( |
|
|
|
/// <returns>A <see cref="StyledProperty{TValue}"/></returns>
|
|
|
|
public static StyledProperty<TValue> Register<TOwner, TValue>( |
|
|
|
string name, |
|
|
|
TValue defaultValue = default(TValue), |
|
|
|
bool inherits = false, |
|
|
|
BindingMode defaultBindingMode = BindingMode.OneWay, |
|
|
|
Func<TOwner, TValue, TValue> validate = null, |
|
|
|
Action<PerspexObject, bool> notifying = null) |
|
|
|
where TOwner : PerspexObject |
|
|
|
Action<IPerspexObject, bool> notifying = null) |
|
|
|
where TOwner : IPerspexObject |
|
|
|
{ |
|
|
|
Contract.Requires<ArgumentNullException>(name != null); |
|
|
|
|
|
|
|
PerspexProperty<TValue> result = new PerspexProperty<TValue>( |
|
|
|
var result = new StyledProperty<TValue>( |
|
|
|
name, |
|
|
|
typeof(TOwner), |
|
|
|
defaultValue, |
|
|
|
inherits, |
|
|
|
defaultBindingMode, |
|
|
|
Cast(validate), |
|
|
|
notifying, |
|
|
|
false); |
|
|
|
|
|
|
|
PerspexPropertyRegistry.Instance.Register(typeof(TOwner), result); |
|
|
|
|
|
|
|
return result; |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Registers a direct <see cref="PerspexProperty"/>.
|
|
|
|
/// </summary>
|
|
|
|
/// <typeparam name="TOwner">The type of the class that is registering the property.</typeparam>
|
|
|
|
/// <typeparam name="TValue">The type of the property's value.</typeparam>
|
|
|
|
/// <param name="name">The name of the property.</param>
|
|
|
|
/// <param name="getter">Gets the current value of the property.</param>
|
|
|
|
/// <param name="setter">Sets the value of the property.</param>
|
|
|
|
/// <returns>A <see cref="PerspexProperty{TValue}"/></returns>
|
|
|
|
public static PerspexProperty<TValue> RegisterDirect<TOwner, TValue>( |
|
|
|
string name, |
|
|
|
Func<TOwner, TValue> getter, |
|
|
|
Action<TOwner, TValue> setter = null) |
|
|
|
where TOwner : PerspexObject |
|
|
|
{ |
|
|
|
Contract.Requires<ArgumentNullException>(name != null); |
|
|
|
|
|
|
|
PerspexProperty<TValue> result = new PerspexProperty<TValue>( |
|
|
|
name, |
|
|
|
typeof(TOwner), |
|
|
|
Cast(getter), |
|
|
|
Cast(setter)); |
|
|
|
notifying); |
|
|
|
|
|
|
|
PerspexPropertyRegistry.Instance.Register(typeof(TOwner), result); |
|
|
|
|
|
|
|
@ -474,24 +302,23 @@ namespace Perspex |
|
|
|
/// <param name="defaultBindingMode">The default binding mode for the property.</param>
|
|
|
|
/// <param name="validate">A validation function.</param>
|
|
|
|
/// <returns>A <see cref="PerspexProperty{TValue}"/></returns>
|
|
|
|
public static PerspexProperty<TValue> RegisterAttached<TOwner, THost, TValue>( |
|
|
|
public static AttachedProperty<TValue> RegisterAttached<TOwner, THost, TValue>( |
|
|
|
string name, |
|
|
|
TValue defaultValue = default(TValue), |
|
|
|
bool inherits = false, |
|
|
|
BindingMode defaultBindingMode = BindingMode.OneWay, |
|
|
|
Func<PerspexObject, TValue, TValue> validate = null) |
|
|
|
Func<THost, TValue, TValue> validate = null) |
|
|
|
where THost : IPerspexObject |
|
|
|
{ |
|
|
|
Contract.Requires<ArgumentNullException>(name != null); |
|
|
|
|
|
|
|
PerspexProperty<TValue> result = new PerspexProperty<TValue>( |
|
|
|
var result = new AttachedProperty<TValue>( |
|
|
|
name, |
|
|
|
typeof(TOwner), |
|
|
|
defaultValue, |
|
|
|
inherits, |
|
|
|
defaultBindingMode, |
|
|
|
validate, |
|
|
|
null, |
|
|
|
true); |
|
|
|
Cast(validate)); |
|
|
|
|
|
|
|
PerspexPropertyRegistry.Instance.Register(typeof(THost), result); |
|
|
|
|
|
|
|
@ -516,25 +343,46 @@ namespace Perspex |
|
|
|
TValue defaultValue = default(TValue), |
|
|
|
bool inherits = false, |
|
|
|
BindingMode defaultBindingMode = BindingMode.OneWay, |
|
|
|
Func<PerspexObject, TValue, TValue> validate = null) |
|
|
|
Func<THost, TValue, TValue> validate = null) |
|
|
|
where THost : IPerspexObject |
|
|
|
{ |
|
|
|
Contract.Requires<ArgumentNullException>(name != null); |
|
|
|
|
|
|
|
PerspexProperty<TValue> result = new PerspexProperty<TValue>( |
|
|
|
var result = new AttachedProperty<TValue>( |
|
|
|
name, |
|
|
|
ownerType, |
|
|
|
defaultValue, |
|
|
|
inherits, |
|
|
|
defaultBindingMode, |
|
|
|
validate, |
|
|
|
null, |
|
|
|
true); |
|
|
|
Cast(validate)); |
|
|
|
|
|
|
|
PerspexPropertyRegistry.Instance.Register(typeof(THost), result); |
|
|
|
|
|
|
|
return result; |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Registers a direct <see cref="PerspexProperty"/>.
|
|
|
|
/// </summary>
|
|
|
|
/// <typeparam name="TOwner">The type of the class that is registering the property.</typeparam>
|
|
|
|
/// <typeparam name="TValue">The type of the property's value.</typeparam>
|
|
|
|
/// <param name="name">The name of the property.</param>
|
|
|
|
/// <param name="getter">Gets the current value of the property.</param>
|
|
|
|
/// <param name="setter">Sets the value of the property.</param>
|
|
|
|
/// <returns>A <see cref="PerspexProperty{TValue}"/></returns>
|
|
|
|
public static DirectProperty<TOwner, TValue> RegisterDirect<TOwner, TValue>( |
|
|
|
string name, |
|
|
|
Func<TOwner, TValue> getter, |
|
|
|
Action<TOwner, TValue> setter = null) |
|
|
|
where TOwner : IPerspexObject |
|
|
|
{ |
|
|
|
Contract.Requires<ArgumentNullException>(name != null); |
|
|
|
|
|
|
|
var result = new DirectProperty<TOwner, TValue>(name, getter, setter); |
|
|
|
PerspexPropertyRegistry.Instance.Register(typeof(TOwner), result); |
|
|
|
return result; |
|
|
|
} |
|
|
|
|
|
|
|
/// <inheritdoc/>
|
|
|
|
public override bool Equals(object obj) |
|
|
|
{ |
|
|
|
@ -570,56 +418,6 @@ namespace Perspex |
|
|
|
}; |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Gets the default value for the property on the specified type.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="type">The type.</param>
|
|
|
|
/// <returns>The default value.</returns>
|
|
|
|
public object GetDefaultValue(Type type) |
|
|
|
{ |
|
|
|
Contract.Requires<ArgumentNullException>(type != null); |
|
|
|
|
|
|
|
while (type != null) |
|
|
|
{ |
|
|
|
object result; |
|
|
|
|
|
|
|
if (_defaultValues.TryGetValue(type, out result)) |
|
|
|
{ |
|
|
|
return result; |
|
|
|
} |
|
|
|
|
|
|
|
type = type.GetTypeInfo().BaseType; |
|
|
|
} |
|
|
|
|
|
|
|
return _defaultValue; |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Gets the validation function for the property on the specified type.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="type">The type.</param>
|
|
|
|
/// <returns>
|
|
|
|
/// The validation function, or null if no validation function registered for this type.
|
|
|
|
/// </returns>
|
|
|
|
public Func<PerspexObject, object, object> GetValidationFunc(Type type) |
|
|
|
{ |
|
|
|
Contract.Requires<ArgumentNullException>(type != null); |
|
|
|
|
|
|
|
while (type != null) |
|
|
|
{ |
|
|
|
Func<PerspexObject, object, object> result; |
|
|
|
|
|
|
|
if (_validation.TryGetValue(type, out result)) |
|
|
|
{ |
|
|
|
return result; |
|
|
|
} |
|
|
|
|
|
|
|
type = type.GetTypeInfo().BaseType; |
|
|
|
} |
|
|
|
|
|
|
|
return null; |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Checks whether the <paramref name="value"/> is valid for the property.
|
|
|
|
/// </summary>
|
|
|
|
@ -630,59 +428,6 @@ namespace Perspex |
|
|
|
return TypeUtilities.TryCast(PropertyType, value, out value); |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Overrides the default value for the property on the specified type.
|
|
|
|
/// </summary>
|
|
|
|
/// <typeparam name="T">The type.</typeparam>
|
|
|
|
/// <param name="defaultValue">The default value.</param>
|
|
|
|
public void OverrideDefaultValue<T>(object defaultValue) |
|
|
|
{ |
|
|
|
OverrideDefaultValue(typeof(T), defaultValue); |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Overrides the default value for the property on the specified type.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="type">The type.</param>
|
|
|
|
/// <param name="defaultValue">The default value.</param>
|
|
|
|
public void OverrideDefaultValue(Type type, object defaultValue) |
|
|
|
{ |
|
|
|
Contract.Requires<ArgumentNullException>(type != null); |
|
|
|
|
|
|
|
if (!TypeUtilities.TryCast(PropertyType, defaultValue, out defaultValue)) |
|
|
|
{ |
|
|
|
throw new InvalidOperationException(string.Format( |
|
|
|
"Invalid value for Property '{0}': {1} ({2})", |
|
|
|
Name, |
|
|
|
defaultValue, |
|
|
|
defaultValue.GetType().FullName)); |
|
|
|
} |
|
|
|
|
|
|
|
if (_defaultValues.ContainsKey(type)) |
|
|
|
{ |
|
|
|
throw new InvalidOperationException("Default value is already set for this property."); |
|
|
|
} |
|
|
|
|
|
|
|
_defaultValues.Add(type, defaultValue); |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Overrides the validation function for the property on the specified type.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="type">The type.</param>
|
|
|
|
/// <param name="validation">The validation function.</param>
|
|
|
|
public void OverrideValidation(Type type, Func<PerspexObject, object, object> validation) |
|
|
|
{ |
|
|
|
Contract.Requires<ArgumentNullException>(type != null); |
|
|
|
|
|
|
|
if (_validation.ContainsKey(type)) |
|
|
|
{ |
|
|
|
throw new InvalidOperationException("Validation is already set for this property."); |
|
|
|
} |
|
|
|
|
|
|
|
_validation.Add(type, validation); |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Gets the string representation of the property.
|
|
|
|
/// </summary>
|
|
|
|
@ -711,45 +456,24 @@ namespace Perspex |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Casts a getter function accepting a typed owner to one accepting a
|
|
|
|
/// <see cref="PerspexObject"/>.
|
|
|
|
/// Casts a validation function accepting a typed owner to one accepting an
|
|
|
|
/// <see cref="IPerspexObject"/>.
|
|
|
|
/// </summary>
|
|
|
|
/// <typeparam name="TOwner">The owner type.</typeparam>
|
|
|
|
/// <typeparam name="TValue">The property value type.</typeparam>
|
|
|
|
/// <param name="f">The typed function.</param>
|
|
|
|
/// <returns>The untyped function.</returns>
|
|
|
|
private static Func<PerspexObject, TValue> Cast<TOwner, TValue>(Func<TOwner, TValue> f) |
|
|
|
where TOwner : PerspexObject |
|
|
|
protected static Func<IPerspexObject, TValue, TValue> Cast<TOwner, TValue>(Func<TOwner, TValue, TValue> f) |
|
|
|
where TOwner : IPerspexObject |
|
|
|
{ |
|
|
|
return (f != null) ? o => f((TOwner)o) : (Func<PerspexObject, TValue >)null; |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Casts a setter action accepting a typed owner to one accepting a
|
|
|
|
/// <see cref="PerspexObject"/>.
|
|
|
|
/// </summary>
|
|
|
|
/// <typeparam name="TOwner">The owner type.</typeparam>
|
|
|
|
/// <typeparam name="TValue">The property value type.</typeparam>
|
|
|
|
/// <param name="f">The typed action.</param>
|
|
|
|
/// <returns>The untyped action.</returns>
|
|
|
|
private static Action<PerspexObject, TValue> Cast<TOwner, TValue>(Action<TOwner, TValue> f) |
|
|
|
where TOwner : PerspexObject |
|
|
|
{ |
|
|
|
return f != null ? (o, v) => f((TOwner)o, v) : (Action<PerspexObject, TValue>)null; |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Casts a validation function accepting a typed owner to one accepting a
|
|
|
|
/// <see cref="PerspexObject"/>.
|
|
|
|
/// </summary>
|
|
|
|
/// <typeparam name="TOwner">The owner type.</typeparam>
|
|
|
|
/// <typeparam name="TValue">The property value type.</typeparam>
|
|
|
|
/// <param name="f">The typed function.</param>
|
|
|
|
/// <returns>The untyped function.</returns>
|
|
|
|
private static Func<PerspexObject, TValue, TValue> Cast<TOwner, TValue>(Func<TOwner, TValue, TValue> f) |
|
|
|
where TOwner : PerspexObject |
|
|
|
{ |
|
|
|
return f != null ? (o, v) => f((TOwner)o, v) : (Func<PerspexObject, TValue, TValue>)null; |
|
|
|
if (f == null) |
|
|
|
{ |
|
|
|
return null; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
return (o, v) => f((TOwner)o, v); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
@ -761,10 +485,7 @@ namespace Perspex |
|
|
|
/// Returns the string representation of the <see cref="UnsetValue"/>.
|
|
|
|
/// </summary>
|
|
|
|
/// <returns>The string "(unset)".</returns>
|
|
|
|
public override string ToString() |
|
|
|
{ |
|
|
|
return "(unset)"; |
|
|
|
} |
|
|
|
public override string ToString() => "(unset)"; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|