Jump to content
  • Advanced Event Handling with Spotfire® API


    Introduction

    In certain cases, the structure, or layered structure of a custom node may make it difficult or impossible to create simple PropertyTriggers, MutableTriggers or SubTreeTriggers to expose to the outside the correct event generated in document nodes owned by the custom node in question.

    Most custom nodes will not not require event relays, but custom nodes containing complex structures of other document nodes may need to implement them to be able to propagate change events in a correct way.

    This article attempts to shine some light on the concepts of event relays and the inner workings of the mutable property trigger.

    Prerequisites

    Events and Complex DocumentNode Structures

    Usually a PropertyTrigger, MutablePropertyTrigger or a SubTreeTrigger would suffice to listen to changes to document node's properties. Especially convenient in complex cases would be the SubTreeTrigger that allows for listening to all node changes of a particular type in a subtree of the document, such as the page title of all pages in the document. But in complex cases, or for convenience and clarity reasons, just using these three trigger types might for different reasons not work well in all cases.

    By creating EventRelays it is possible for a custom node to define a PropertyName whose sole purpose is relay events from child or referenced document nodes. One typical use case would be the exposing of events from items stored inside custom node wrappers inside containers such as the DocumentNodeList class.

    A Minimal Example

    Assume that there is a need to 

    1. Store multiple DataMarkingSelections in a collection class
    2. Detect any DataSelection change in the collection of DataMarkingSelections 

    A convenient way to store DataMarkingSelections would be to put them in a DocumentNodeList. However, since the DataMarkingSelections are likely owned by the Document instance, they need to be referenced using a UndoableCrossReferenceProperty rather than stored directly in the DocumentNodeList. This can be achieved by creating a MarkingReference class inheriting from CustomNode.

    Example Code

    C#

    public sealed class MarkingReferenceList : DocumentNodeList<MarkingReference>
    {
    ....
    }
     
    public sealed class MarkingReference : CustomNode
    {
        private readonly UndoableCrossReferenceProperty<DataMarkingSelection> _dataMarkingSelection;
    
        public new class PropertyNames : CustomNode.PropertyNames
        {
            public static readonly PropertyName Marking = CreatePropertyName("Marking");
            public static readonly PropertyName MarkingSelection = CreatePropertyName("MarkingSelection");
        }
    
        
        private void InitEventRelays()
        {
            CreateEventRelay(PropertyNames.MarkingSelection,
                delegate
                {
                    return Trigger.CreateMutablePropertyTrigger<DataMarkingSelection>(
                    this, PropertyNames.Marking, DataSelection.PropertyNames.Selection);
                });
        }
        
        ...
     

    MarkingReference Class Explained

    The MarkingReference class above has

    1. A cross-reference to the DataMarkingSelection it is to contain
    2. Two property names:
      • "Marking" which is the PropertyName of the DataMarkingSelection in (1)
      • "MarkingSelection" which is the PropertyName of the event relay used to relay the contained DataMarkingSelection's selection changes.
    3. An InitEventRelays() method to create the event relay for "MarkingSelection" property. Since the MarkingReference should propagate Selection change events even if the internal DataMarkingSelection object changes, it needs to be defined as a mutable Trigger for the DataMarkingSelection "Marking".

      N.b. The EventRelay must be initialized 

      • In the CustomNode's constructor
      • In the CustomNode's deserialization constructor

    Mutable Triggers Demystified

    The code above uses syntactical sugar when creating the mutable trigger, to abbreviate the code to simplify the most common use case; the need to re-subscribe to a  property on a DocumentNode that may be changed for another DocumentNode by the user.

    However,  mutable property triggers can be better understood if written like this:

    Trigger.CreateMutablePropertyTrigger<DataMarkingSelection>(this, PropertyNames.Marking, 
    	delegate(DataMarkingSelection dms)
    	{
    		return Trigger.CreatePropertyTrigger(dms, DataSelection.PropertyNames.Selection);
    	});
     

    When the DataMarkingSelection object references changes in the MarkingReference wrapper, the MarkingReference class is automatically starting to relay Selection events to its "MarkingSelection" property. The trigger created by the delegate may ofcourse do something more advanced than just return a simpler property trigger.

    Creating Triggers From the EventRelay

    At this point, to listen to any DataSelection.PropertyNames.Selection changes in the DataMarkingSelections of the MarkingReferenceList one could subscribe to the MarkingSelection EventRelay. 

    private readonly MarkingReferenceList _markings;
    ...
        Trigger.CreateSubTreeTrigger(_markings, typeof(MarkingReference), MarkingReference.PropertyNames.MarkingSelection);
    ...
     

    Advanced Use Cases

    Event relays become more powerful and useful in the cases where the sub nodes of a CustomNode container are a little bit more complex than the above example, e.g.

    • its items contain multiple DataSelection containers that needs to be handled differently
    • combine different triggers from different layers in the code that can be to be combined to a logical trigger through the creation of  an event relay to make it easier to subscribe to the proper changes

    eventrelayexample_0.zip


    User Feedback

    Recommended Comments

    There are no comments to display.


×
×
  • Create New...