Skip to main content
RSS feed Subscribe to feed

 

Undoable Cross Reference Properties

Undoable Cross Reference Properties are fields that contain references to other document nodes. They enable the Document Model Framework to observe changes to the monitored field.

Overview

Undoable cross reference properties are similar to undoable properties. The difference is that the node referenced by an undoable cross reference property is not considered to be owned by that property. If a node that is referred to by an undoable cross referenced property is removed from the document, the value of the undoable cross reference property becomes null. A cross reference property never keeps a dangling reference to a node that is no longer a part of the document.

Cross reference properties are useful when you want to act on a node without owning it. Consider a bookmark that refers to a page: Applying the bookmark makes that page active, but the page is still not owned by the bookmark. If the bookmark is removed, the page remains a node in the page collection at the top level of the document.

UndoableCrossReferenceProperties commonly reference the data DataTable or DataColumns a visualization, a tool or a panel will use.

The framework provides a single class for undoable cross reference properties:

Implementation Pattern

The following example defines a ReferenceNode property which holds a reference to a document node of type SomeNode. It is built in a steps:

  1. Define a Property Name for the property.
  2. Define a private field of type UndoableCrossReferenceProperty<SomeNode>.
  3. Define a property with a
    • get accessor that reads the Value property from the undoable property
    • set accessor that sets the Value property.
  4. In the constructor of the class, create the property using the CreateProperty method.
  5. In the GetObjectData method, serialize the property using the SerializeProperty method.
  6. In the deserialization constructor, deserialize the property using the DeserializeProperty method.
[Serializable]
public sealed class NodeWithReference : DocumentNode
{
    public new sealed class PropertyNames : DocumentNode.PropertyNames
    {
        public static PropertyName ReferencedNode = CreatePropertyName("ReferencedNode");
    }

    private readonly UndoableCrossReferenceProperty<SomeNode> referencedNode;

    /// <summary/>
    public NodeWithReference(SomeNode someNode)
    {
        CreateProperty<SomeNode>(
           PropertyNames.ReferencedNode, 
           out this.referencedNode, 
           someNode);
    }

    /// <summary>The referenced node.</summary>
    public SomeNode ReferencedNode
    {
        get { return this.referencedNode.Value; }
        set { this.referencedNode.Value = value; }
    }

    protected override void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        base.GetObjectData(info, context);

        SerializeProperty(info, context, this.referencedNode);
    }

    internal NodeWithReference(SerializationInfo info, StreamingContext context) : base(info, context)
    {
        DeserializeProperty(
           info, 
           context, 
           PropertyNames.ReferencedNode,
           out this.referencedNode);
    }

}