A storage for properties and events of a class
Remarks: This is used by Widget object to minimize the footprint of each instance. For example, the Control class has around 20 events, each would take up to 4 bytes on a 32 bit system for a total overhead of 80 bytes per instance. Most of the events won't be handled on most controls, so using a dictionary can dramatically reduce the size. This can also be used for rarely used properties that do not need to be extremely performant when getting or setting the value.
Constructors
PropertyStore
#Initializes a new instance of the PropertyStore class.
Parameters:
| parent (object) | Parent to attach the properties to |
Properties
Parent
#Gets the parent object that this property store is attached to
Remarks: This is used to attach/remove events
Value: The parent object
Methods
AddEvent
#Adds a generic event delegate with the specified key
Remarks: This should be called in an event's add accessor. If you are adding a handler-based event, call AddHandlerEvent(string, Delegate) instead, which will automatically tell the handler that it needs to be wired up. You can use any subclass of EventArgs for the type of event handler To trigger the event, use TriggerEvent<T>(object, object, T).
Example:Example implementation of a generic event
static readonly object MySomethingEventKey = new object();
public event EventHandler<EventArgs> MySomething
{
add { Properties.AddEvent(MySomethingEvent, value); }
remove { Properties.RemoveEvent(MySomethingEvent, value); }
}AddHandlerEvent
#Adds a handler-based event delegate with the specified key
Remarks: This should be called in an event's add accessor. This is used for any event that should be triggered by the platform handler. This will call HandleEvent with the specified
key for the first subscription to the event. You can use any subclass of EventArgs for the type of event handler To trigger the event, use TriggerEvent<T>(object, object, T)Example:Example implementation of a handler-triggered event
public const string MySomethingEvent = "MyControl.MySomething";
public event EventHandler<EventArgs> MySomething
{
add { Properties.AddHandlerEvent(MySomethingEvent, value); }
remove { Properties.RemoveHandlerEvent(MySomethingEvent, value); }
}Create<T>
#Gets a value from the property store with the specified key of a concrete type, and creates a new instance if it doesn't exist yet.
Create<T>
#Gets a value from the property store with the specified key of a concrete type, and creates a new instance if it doesn't exist yet.
Parameters:
| key (object) | Key of the property to get |
Returns: Value of the property with the given key, or a new instance if not already added
Get<T>
#Gets a value from the property store with the specified key of a concrete type
Get<T>
#Gets a value from the property store with the specified key of a concrete type
Parameters:
| key (object) | Key of the property to get |
| defaultValue (T = null) | Value to return when the specified property is not found in the dictionary |
Returns: Value of the property with the given key, or
defaultValue if not foundGetCommand
#Gets the command instance for the specified property key.
Parameters:
| key (object) | Key of the property to get. |
Returns: The command instance, or null if it is not set.
RemoveEvent
#Removes the event delegate with the specified
keyRemarks: Use this in the remove accessor of your event. See AddEvent(object, Delegate) and AddHandlerEvent(string, Delegate) for examples.
Removes a handler-based event delegate with the specified
key, telling the handler to stop listening once the last subscriber is gone.Remarks: Use this in the remove accessor of an event added with AddHandlerEvent(string, Delegate) when the platform holds onto something worth giving back while the event is attached, such as a system wide hook. RemoveEvent(object, Delegate) leaves the event attached for the life of the widget, which is fine and cheaper for the vast majority of events. The handler is only told once nothing is subscribed any more, and never for an event that is attached because the widget overrides its On[Event] method, since that has to keep firing. A handler that can't detach the event says so, and it stays attached.
Set<T>
#Set the value for the specified property key, calling the
propertyChanged delegate if it has changed.Remarks: This is useful when creating properties that need to trigger changed events without having to write boilerplate code.
Parameters:
| key (object) | Key of the property to set. |
| value (T) | Value for the property. |
| propertyChanged (Action) | Property changed event handler to raise if the property value has changed. |
| defaultValue (T = null) | Default value of the property to compare when removing the key |
Returns: true if the property was changed, false if not
Example:
public class MyForm : Form
{
static readonly MyPropertyKey = new object();
public bool MyProperty
{
get { return Properties.Get<bool>(MyPropertyKey); }
set { Properties.Set(MyPropertyKey, value, OnMyPropertyChanged); }
}
public event EventHandler<EventArgs> MyPropertyChanged;
protected virtual void MyPropertyChanged(EventArgs e)
{
if (MyPropertyChanged != null)
MyPropertyChanged(this, e);
}
}Set<T>
#public bool Set<T>(object key, T value, PropertyChangedEventHandler propertyChanged, T defaultValue = default(T), string propertyName = null)
Set the value for the specified property key, raising the
propertyChanged handler if it has changed.Remarks: This is useful when creating properties that need to trigger changed events without having to write boilerplate code.
Parameters:
| key (object) | Key of the property to set. |
| value (T) | Value for the property. |
| propertyChanged (PropertyChangedEventHandler) | Property changed event handler to raise if the property value has changed. |
| defaultValue (T = null) | Default value of the property to compare when removing the key |
| propertyName (string = null) | Name of the property, or omit to get the property name from the caller. |
Returns: true if the property was changed, false if not
Example:
public class MyForm : Form, INotifyPropertyChanged
{
static readonly MyPropertyKey = new object();
public bool MyProperty
{
get { return Properties.Get<bool>(MyPropertyKey); }
set { Properties.Set(MyPropertyKey, value, PropertyChanged); }
}
public event PropertyChangedEventHandler PropertyChanged;
}Set<T>
#Set the value for the specified property key, removing the value from the dictionary if it is the default value of T.
Remarks: This can be used as an optimized way to set the value in the dictionary as if the value set equal to the
defaultValue (e.g. null for reference types, false for bool, 0 for int, etc), then it will be removed from the dictionary instead of just set to the value, reducing memory usage. The Get<T>(object, T) should be passed the same default when retrieving the parameter value.Parameters:
| key (object) | Key of the property to set. |
| value (T) | Value for the property. |
| defaultValue (T = null) | Value of the property when it should be removed from the dictionary. This should match what is passed to Get<T>(object, T) when getting the value. |
SetCommand
#Sets an ICommand value for the specified property
key.Parameters:
| key (object) | Key of the property to set |
| value (ICommand) | Command instance |
| setEnabled (Action<bool>) | Delegate to set the widget as enabled when the command state changes. |
| addExecute (Action<EventHandler<EventArgs>>) | Delegate to attach the execute event handler when the widget invokes the command. |
| removeExecute (Action<EventHandler<EventArgs>>) | Delegate to detach the execute event handler. |
| getParameter (Func<object>) | Delegate to get the parameter to pass to the command |
See Also: GetCommand(object)
TriggerEvent<T>
#Triggers an event with the specified key
Remarks: Call this in your OnMyEvent(EventArgs) method to trigger the event if it has been subscribed to. This can handle events that have any type of EventArgs.
Parameters:
| key (object) | Key of the generic or handler event |
| sender (object) | Object sending the event (usually 'this') |
| args (T) | Arguments for the event |
Example:This shows how to trigger either a generic event or handler-triggered event:
protected virtual void OnMySomething(EventArgs e)
{
Properties.TriggerEvent(MySomethingEventKey, this, e);
}TrySet<T>
#Set the value for the specified property key, removing the value from the dictionary if it is the default value of T.
Remarks: This can be used as an optimized way to set the value in the dictionary as if the value set equal to the default value. (e.g. null for reference types, false for bool, 0 for int, etc), then it will be removed from the dictionary instead of just set to the value, reducing memory usage.
Parameters:
| key (object) | Key of the property to set. |
| value (T) | Value for the property. |
| defaultValue (T = null) | Value of the property when it should be removed from the dictionary. This should match what is passed to Get<T>(object, T) when getting the value. |
Returns:
true if the value was changed, false otherwise.Unbinds the command associated with the specified key, removing its registration.
Remarks: If the command associated with the specified key is found, it will be unregistered, allowing for cleanup of resources or state related to the command.
Parameters:
| key (object) | The key used to identify the command to be unbound. Cannot be null. |