Table of Contents

Interface IDiagramModel

Namespace
StockSharp.Xaml.Diagram.GXDiagram.Model
Assembly
StockSharp.Xaml.Diagram.dll

All diagram models implement this interface or an interface that inherits from this interface.

public interface IDiagramModel
Extension Methods

Remarks

This is reponsible for defining relationships between nodes, involving links and grouping. It does not know about any FrameworkElements (including Diagram or DiagramPanel or Part). It just knows about .NET CLR objects as data of type object or about more specific types when instantiating one of the generic StockSharp.Xaml.Diagram.GXDiagram.Model.DiagramModel classes. It is vaguely analogous to a CollectionView, providing additional organization of the source data. It defines a graph from the data instead of imposing a total ordering on it and filtering/sorting/grouping it. It also supports two-pass copying of existing data and undo/redo support via an UndoManager.

There are four categories of members in this interface: updating, navigation, modification, and miscellaneous. The updating methods need to be called when there has been a change to the data, so that the model can be kept up-to-date with the data. The navigation methods support examining the diagram and traversing the graph defined by the nodes and links in the diagram. The modification methods are used to alter the diagram. The miscellaneous methods and properties include support for model change notification, for undo/redo, for edits, and for data transfer. Additional categories of members exist in each of the model classes.

The most important member of this interface is the NodesSource property, the collection of node data defining the graph. You will need to set it before anything can be seen in your Diagram. The model will look at each node data in that collection to discover the relationships that will form the graph. The methods and properties for discovering a graph from the data depend on the kind of model, so they are not part of this interface.

As data is added or removed from the model, or as data is modified, the graph implied by the data changes. Whenever the data is modified, the model must be notified. The model interfaces (both this interface and more specific interfaces inheriting from this interface) have a category of methods for being notified of data changes. This basic interface includes methods such as DoNodeAdded(object), DoNodeRemoved(object), and DoNodeKeyChanged(object). More specific kinds of models have additional methods, such as: StockSharp.Xaml.Diagram.GXDiagram.Model.ITreeModel.DoParentNodeChanged(System.Object), StockSharp.Xaml.Diagram.GXDiagram.Model.IConnectedModel.DoToNodeKeyRemoved(System.Object,System.Object), StockSharp.Xaml.Diagram.GXDiagram.Model.ILinksModel.DoLinkAdded(System.Object), StockSharp.Xaml.Diagram.GXDiagram.Model.IGroupsModel.DoMemberNodeKeysChanged(System.Object), and StockSharp.Xaml.Diagram.GXDiagram.Model.ISubGraphModel.DoGroupNodeChanged(System.Object). Updating methods have names that start with "Do".

Of course if your data is unchanging, neither by application code nor by the user, you will not need to be concerned about keeping the model up-to-date. But if your data might change, .NET provides some standard interfaces for change notification that you should use if you want successful data binding.

The INotifyPropertyChanged interface (in the System.ComponentModel namespace) is commonly used for notification of property changes. The diagram model classes automatically register themselves as INotifyPropertyChanged.PropertyChanged event listeners for each of the data objects that are in the NodesSource collection so that they can be updated if a model-relevant property changes in a data object. We suggest that you have your node data class implement this interface, but that you use the ModelChangedEventArgs class for event arguments instead of PropertyChangedEventArgs.

In addition, Microsoft recommends implementing the INotifyCollectionChanged interface (in the System.Collections.Specialized namespace) for providing change notification of collection objects. .NET offers the ObservableCollection<T> class as a standard collection that implements INotifyCollectionChanged. So if the collection you supply as the value of NodesSource implements this interface, the model will automatically call the DoNodeAdded(object) and DoNodeRemoved(object) methods for you. Similarly, for the data properties that are expected to be collections, (such as the collection of tree children nodes for a data node in the tree model), we suggest you use ObservableCollection<T>. Note that the optional data classes that we provide for your use, if you do not already have your own data classes, implement INotifyPropertyChanged and make use of ObservableCollection<T>. An example is StockSharp.Xaml.Diagram.GXDiagram.Model.TreeModelNodeData`1.

The generic model classes have a parameterized type, NodeType, that denotes the type of the node data that it contains. That of course is the required type of each item in the NodesSource collection. Furthermore, all of the methods that operate on node data take and/or return that type. This design provides for better type checking at compile time and potentially better performance at run time.

But IDiagramModel and its subinterfaces are not generic. Their methods all take and/or return data of type Object instead of a parameterized type. This "universality" is necessary because the diagram control is not a generic class.

Unlike most controls that bind to a list of items, diagrams involve relationships between the items that are much more general than just the order in the list. This is achieved by interpreting some property values as "references" to other data. Such references might be implemented as .NET CLR references (i.e. pointers). However, it is also common to use other values, such as strings or numbers, as the references. Such a scheme requires being able to identify each data object with a unique value.

The generic model class have another parameterized type, NodeKey, that denotes the type of the values that refer to node data. When the abstract references are actually .NET CLR references, the NodeKey type will be the same as the NodeType type. But more often the NodeKey will be something like String or int.

Normally the expectation is that the key value for each node data does not change. However, the models do support such a circumstance -- make sure the DoNodeKeyChanged(object) method is called right after changing a node's key.

The FindNodeByKey(object) method is useful for finding a node data given its key. To find out if a node data is in the NodesSource collection, call the IsNodeData(object) predicate.

The models have a number of methods that are useful for examining or navigating. These method names tend to start with "Get" or "Is". For "link" relationships, the following methods apply to all models: IsLinked(object, object, object, object), GetFromNodesForNode(object), GetToNodesForNode(object), GetConnectedNodesForNode(object). Particular kinds of models have additional methods for traversing graphs, such as: StockSharp.Xaml.Diagram.GXDiagram.Model.ITreeModel.GetChildrenForNode(System.Object), StockSharp.Xaml.Diagram.GXDiagram.Model.ILinksModel.GetLinksBetweenNodes(System.Object,System.Object,System.Object,System.Object), StockSharp.Xaml.Diagram.GXDiagram.Model.ILinksModel.GetToNodeForLink(System.Object), StockSharp.Xaml.Diagram.GXDiagram.Model.ILinksModel.GetLabelNodeForLink(System.Object), StockSharp.Xaml.Diagram.GXDiagram.Model.IGroupsModel.GetMemberNodesForGroup(System.Object), and StockSharp.Xaml.Diagram.GXDiagram.Model.ISubGraphModel.GetGroupForNode(System.Object). Note that the models will have similar protected (not public) methods that actually implement the corresponding behavior on the data. There will be virtual so that your model implementation can customize or optimize how the method performs the operation.

The models also have methods for modifying. These method names start with "Modify", "Add", or "Remove". For nodes, there are AddNode(object) and RemoveNode(object). For links, there are AddLink(object, object, object, object) and RemoveLink(object, object, object, object). Furthermore, particular kinds of models have additional methods for changing relationships, such as: StockSharp.Xaml.Diagram.GXDiagram.Model.ITreeModel.AddChildNodeKey(System.Object,System.Object), StockSharp.Xaml.Diagram.GXDiagram.Model.IConnectedModel.AddFromNodeKey(System.Object,System.Object), StockSharp.Xaml.Diagram.GXDiagram.Model.ILinksModel.SetLinkLabel(System.Object,System.Object), StockSharp.Xaml.Diagram.GXDiagram.Model.IGroupsModel.RemoveMemberNodeKey(System.Object,System.Object), and StockSharp.Xaml.Diagram.GXDiagram.Model.ISubGraphModel.SetGroupNode(System.Object,System.Object). Note that the models will have similar protected (not public) methods that actually implement the corresponding behavior on the data. There will be virtual so that your model implementation can customize or optimize how the method performs the modification.

Finally, there is the Modifiable property, that should disable user actions that would modify the model, and that causes errors when you call a model-modifying method anyway.

Models support a two-pass copying process. A single pass copy is insufficient because some "references" cannot be made before all objects have been copied -- those references need to be fixed-up afterwards, in a second pass. Let's say that we have two objects to be copied, A and B, and that A has a string property that refers to B by its name, "B". After making the two copied objects, A2 and B2, A2's reference will typically still be "B". The second copy pass will operate on A2 and give it a chance to look for the original "B" data, to find the copied B2 data, and to change A2's reference to be "B2".

The principal copying method is AddCollectionCopy(IDataCollection, ICopyDictionary). This first makes copies of all the data to be copied, and then iterates over them again, fixing up the references. You may need to override protected virtual methods whose names start with "Copy" in order to correctly construct copies of your data in the first pass, and in order to correctly fix references to other data in the second pass.

Even after the two-pass copying process has finished, there may still be unresolved references. ClearUnresolvedReferences()

For convenience in making a copy of a node and adding it to the model, there is also the AddNodeCopy(object) method.

Depending on the application, not all relationships should be possible. Models provide support for link relationships with the IsLinkValid(object, object, object, object) method. There are more specific model predicates for IsRelinkValid: StockSharp.Xaml.Diagram.GXDiagram.Model.ILinksModel.IsRelinkValid(System.Object,System.Object,System.Object,System.Object,System.Object), StockSharp.Xaml.Diagram.GXDiagram.Model.IConnectedModel.IsRelinkValid(System.Object,System.Object,System.Object,System.Object), and StockSharp.Xaml.Diagram.GXDiagram.Model.ITreeModel.IsRelinkValid(System.Object,System.Object,System.Object,System.Object). StockSharp.Xaml.Diagram.GXDiagram.Model.IGroupsModel.IsMemberValid(System.Object,System.Object) offers similar support for the group-member relationship in StockSharp.Xaml.Diagram.GXDiagram.Model.IGroupsModel. The diagram control uses these methods for deciding which user actions are permissible. The model classes add support for customizing these methods.

Each model is not only a consumer of events on its data but is also a generator Changed events, to allow model consumers such as the diagram control to keep themselves up-to-date with the model. StockSharp.Xaml.Diagram.GXDiagram.Model.ModelChange is an enumeration that lists all of the kinds of changes that can happen to the predefined model classes. Whenever there is a change to a model, the code calls RaiseChanged(ModelChangedEventArgs) or a similar method to notify model consumers. The IsModified property is automatically set to true as Changed events are raised.

Each model also supports undo and redo, using an UndoManager that records Changed events. Because ModelChangedEventArgs also implements StockSharp.Xaml.Diagram.GXDiagram.Model.IUndoableEdit, it is very easy for the undo manager to remember the changes in a manner that makes them easy to undo or redo. But note that the UndoManager property is initially null; you will need to set this property before any actions can be recorded and then undone. When you want to make transient changes that you do not want to be recorded by the undo manager, you can temporarily set SkipsUndoManager to true.

As you add state to your data or to your model, you may need to add code that implements state changing as needed for undo and redo. This can be done either by overriding a model method or a data method if the data implements StockSharp.Xaml.Diagram.GXDiagram.Model.IChangeDataValue.

A single user gesture or command may result in many model/data changes. These all want to be treated as a single undo-able action. You can group such changes together by calling StartTransaction(string) and CommitTransaction(string). If after a StartTransaction(string) you don't want to commit the changes, you can call RollbackTransaction(), which not only ends the transaction but also automatically "undoes" all of the changes since the call to StartTransaction(string).

Properties

DataFormat

Gets or sets the format of this model's data.

string DataFormat { get; set; }

Property Value

string

By default this is the fully qualified name of this model type.

Remarks

This string is used by clipboard and drag-and-drop operations to distinguish between different and presumably incompatible data sources. You may wish to provide different values in order to prevent data from being transferred to other applications that are using the same model class.

IsChangingModel

This property is true during a call to ChangeModel(ModelChangedEventArgs, bool), indicating a change happening due to an undo or a redo.

bool IsChangingModel { get; }

Property Value

bool

IsInTransaction

True if there is an UndoManager and a transaction has been started.

bool IsInTransaction { get; }

Property Value

bool

IsModified

Gets or sets whether this model is considered changed from an earlier state.

bool IsModified { get; set; }

Property Value

bool

true if this model has been marked as having been modified, if the UndoManager has recorded any changes, or if an undo has been performed without a corresponding redo.

Modifiable

Gets or sets whether various model-changing methods are enabled.

bool Modifiable { get; set; }

Property Value

bool

By default this value is false.

Remarks

When false, this property disables methods named "Add...", "Modify...", or "Remove...".

But note that this property does not and cannot affect the "modifiability" or "read-only"-ness of model data, since the data classes may have no knowledge about this model class and this property.

Name

A name for this model.

string Name { get; set; }

Property Value

string

By default this is an empty string.

Remarks

This is mostly used to help distinguish between different models of the same type.

NodesSource

Gets or sets the collection of node data items for the model.

IEnumerable NodesSource { get; set; }

Property Value

IEnumerable

Initially this value is null. It must be set to a non-null, non-empty value for the model to have any "data".

SkipsUndoManager

Gets or sets a flag that controls whether the model notifies any UndoManager that a change has occurred.

bool SkipsUndoManager { get; set; }

Property Value

bool

This is normally false. You may want to temporarily set this to true in order to avoid recording temporary changes to the model.

UndoManager

Gets or sets the UndoManager for this model.

UndoManager UndoManager { get; set; }

Property Value

UndoManager

When this value is null, there is no UndoManager, and thus no support for undo/redo.

Methods

AddCollectionCopy(IDataCollection, ICopyDictionary)

Copy existing data and add to this model.

ICopyDictionary AddCollectionCopy(IDataCollection coll, ICopyDictionary env)

Parameters

coll IDataCollection

the collection of data to be copied

env ICopyDictionary

the ICopyDictionary used to keep track of copied objects; if null, the method will call CreateCopyDictionary(), use it, and return it

Returns

ICopyDictionary

the updated copy dictionary

Remarks

The primary purpose of this method is to perform a two-pass copy of a part of a diagram, and add the resulting data to this model.

Of course you can add node data without copying them by calling AddNode(object) or by just adding them directly to the NodesSource.

Note that this method is universal, because it can only assume the collections are of type IDataCollection and ICopyDictionary. The corresponding methods in the generic model classes operate on and return a specific collection type.

Add a link between one node/port and another node/port.

object AddLink(object fromdata, object fromparam, object todata, object toparam)

Parameters

fromdata object

a node key identifying the node data from which the link comes

fromparam object

an optional value identifying which port on the "from" node the link is connected to

todata object

a node key identify the node data to which the link goes

toparam object

an optional value identifying which port on the "to" node the link is connected to

Returns

object

Note that this method is universal, because it can only assume the node data is of type object. The corresponding methods in the generic model classes operate on a specific node data type.

AddNode(object)

Add a node data to NodesSource.

void AddNode(object nodedata)

Parameters

nodedata object

Remarks

Note that this method is universal, because it can only assume the node data is of type object. The corresponding methods in the generic model classes operate on a specific node data type.

AddNodeCopy(object)

Add a copy of a node data to this model.

object AddNodeCopy(object nodedata)

Parameters

nodedata object

Returns

object

the copied node data

Remarks

This is a convenience method that just calls AddCollectionCopy(IDataCollection, ICopyDictionary).

Note that this method is universal, because it can only assume the node data is of type object. The corresponding methods in the generic model classes operate on and return a specific node data type.

ChangeModel(ModelChangedEventArgs, bool)

This is called during an Undo or a Redo to actually make state changes to this model or to this model's data.

void ChangeModel(ModelChangedEventArgs e, bool undo)

Parameters

e ModelChangedEventArgs

an edit describing the change to be performed

undo bool

true if undoing; false if redoing

ClearUnresolvedReferences()

Forget all unresolved delayed or forward references.

void ClearUnresolvedReferences()

Remarks

The model may learn about node data in any order, so references to nodes may be unresolvable until later, perhaps never. Call this method to clear the internal table that keeps track of node keys that are not defined by the presence of corresponding node data.

CommitTransaction(string)

Call the UndoManager's CommitTransaction method.

bool CommitTransaction(string tname)

Parameters

tname string

a String describing the transaction

Returns

bool

CreateCopyDictionary()

Create an ICopyDictionary initialized for this model.

ICopyDictionary CreateCopyDictionary()

Returns

ICopyDictionary

Normally this will be an empty dictionary.

CreateDataCollection()

Create an empty IDataCollection for this model.

IDataCollection CreateDataCollection()

Returns

IDataCollection

CreateInitializedCopy(IDataCollection)

Create a copy of this model initialized with different data.

IDiagramModel CreateInitializedCopy(IDataCollection init)

Parameters

init IDataCollection

this may be null, meaning no initial data

Returns

IDiagramModel

a model of the same type as this

Remarks

Most of the properties of the returned model should have the same value as this model, but the data depends on the argument IDataCollection.

DoNodeAdded(object)

This should be called when a node data object is added to the NodesSource collection.

void DoNodeAdded(object nodedata)

Parameters

nodedata object

Remarks

This is used for model update, when the model data has changed and the model itself needs to be updated to reflect those changes. Note that this method is universal, because it can only assume the node data is of type object. The corresponding methods in the generic model classes operate on a specific node data type.

If the NodesSource collection implements INotifyCollectionChanged, the model will automatically call this method. Otherwise, you need to do so immediately after the NodesSource has been augmented.

DoNodeKeyChanged(object)

This should be called when a node data's key value may have changed.

void DoNodeKeyChanged(object nodedata)

Parameters

nodedata object

Remarks

This is used for model update, when the model data has changed and the model itself needs to be updated to reflect those changes. Note that this method is universal, because it can only assume the node data is of type object. The corresponding methods in the generic model classes operate on a specific node data type.

If a node data object implements INotifyPropertyChanged and if the key is a simple property on the data that the model recognizes, the model will automatically call this method. Otherwise, you need to do so immediately after the value of node's key has changed.

DoNodeRemoved(object)

This should be called when a node data object is removed from the NodesSource collection.

void DoNodeRemoved(object nodedata)

Parameters

nodedata object

Remarks

This is used for model update, when the model data has changed and the model itself needs to be updated to reflect those changes. Note that this method is universal, because it can only assume the node data is of type object. The corresponding methods in the generic model classes operate on a specific node data type.

If the NodesSource collection implements INotifyCollectionChanged, the model will automatically call this method. Otherwise, you need to do so immediately after the NodesSource has been diminished.

FindNodeByKey(object)

Given a key, find the node data with that key.

object FindNodeByKey(object key)

Parameters

key object

a value of null for this argument will result in the default value for the node data Type

Returns

object

a node data with that key, if it is present in the model; the value will be the default for the type if no such node data is known to be in this model

Remarks

This is used for model navigation.

Note that this method is universal, because it can only assume the node data is of type object. The corresponding methods in the generic model classes operate on a specific node data type.

GetCategoryForNode(object)

To help distinguish between different kinds of nodes, each node has a "category" that is just a string.

string GetCategoryForNode(object nodedata)

Parameters

nodedata object

Returns

string

the default category is the empty string

GetConnectedNodesForNode(object)

Return a sequence of node data that are directly connected to a given node, in either direction.

IEnumerable<object> GetConnectedNodesForNode(object nodedata)

Parameters

nodedata object

Returns

IEnumerable<object>

an IEnumerable<T>

Remarks

This is used for model navigation and graph traversal.

Note that this method is universal, because it can only assume the node data is of type object. The corresponding methods in the generic model classes operate on a specific node data type.

GetFromNodesForNode(object)

Return a sequence of node data that are directly connected by links going into a given node.

IEnumerable<object> GetFromNodesForNode(object nodedata)

Parameters

nodedata object

Returns

IEnumerable<object>

an IEnumerable<T>

Remarks

This is used for model navigation and graph traversal.

Note that this method is universal, because it can only assume the node data is of type object. The corresponding methods in the generic model classes operate on a specific node data type.

GetNodeType()

Return the Type of the node data.

Type GetNodeType()

Returns

Type

a Type, not a node data object, nor a string

Remarks

This is useful for data transfer.

GetToNodesForNode(object)

Return a sequence of node data that are directly connected by links coming out from a given node.

IEnumerable<object> GetToNodesForNode(object nodedata)

Parameters

nodedata object

Returns

IEnumerable<object>

an IEnumerable<T>

Remarks

This is used for model navigation and graph traversal.

Note that this method is universal, because it can only assume the node data is of type object. The corresponding methods in the generic model classes operate on a specific node data type.

IsLinkValid(object, object, object, object)

This predicate is true if adding a link between two nodes/ports would result in a valid graph.

bool IsLinkValid(object fromdata, object fromparam, object todata, object toparam)

Parameters

fromdata object

a node key identifying the node data from which the link comes

fromparam object

an optional value identifying which port on the "from" node the link is connected to

todata object

a node key identify the node data to which the link goes

toparam object

an optional value identifying which port on the "to" node the link is connected to

Returns

bool

IsLinked(object, object, object, object)

This predicate is true if there is a link from one node data/port to another one.

bool IsLinked(object fromdata, object fromparam, object todata, object toparam)

Parameters

fromdata object

a node key identifying the node data from which the link comes

fromparam object

an optional value identifying which port on the "from" node the link is connected to

todata object

a node key identify the node data to which the link goes

toparam object

an optional value identifying which port on the "to" node the link is connected to

Returns

bool

true if there are any links

Remarks

This is used for model navigation and graph traversal.

Note that this method is universal, because it can only assume the node data is of type object. The corresponding methods in the generic model classes operate on a specific node data type.

IsNodeData(object)

This predicate is true if the argument is a node data in this model.

bool IsNodeData(object nodedata)

Parameters

nodedata object

the object to be checked to see if it is a known node data in this model

Returns

bool

true if the nodedata is in the NodesSource

Remarks

This is used for model navigation.

Note that this method is universal, because it can only assume the node data is of type object. The corresponding methods in the generic model classes operate on a specific node data type.

IsNodeType(object)

This predicate is true when the argument is an instance of the node data Type.

bool IsNodeType(object nodedata)

Parameters

nodedata object

the arbitrary object to be checked for compatibility to be a node data

Returns

bool

true if the nodedata can be cast to the the node data Type; false otherwise

RaiseChanged(ModelChangedEventArgs)

Raise a Changed event, given a ModelChangedEventArgs.

void RaiseChanged(ModelChangedEventArgs e)

Parameters

e ModelChangedEventArgs

a ModelChangedEventArgs that describes what changed and how

Remove all links connecting the two nodes/ports in the one direction.

void RemoveLink(object fromdata, object fromparam, object todata, object toparam)

Parameters

fromdata object

a node key identifying the node data from which the link comes

fromparam object

an optional value identifying which port on the "from" node the link is connected to

todata object

a node key identify the node data to which the link goes

toparam object

an optional value identifying which port on the "to" node the link is connected to

This method can have potential side-effects, such as removing nodes that are labels on the link.

Note that this method is universal, because it can only assume the node data is of type object. The corresponding methods in the generic model classes operate on a specific node data type.

RemoveNode(object)

Remove node data from NodesSource.

void RemoveNode(object nodedata)

Parameters

nodedata object

Remarks

This method can have potential side-effects, such as removing links that are connected to the nodedata.

Note that this method is universal, because it can only assume the node data is of type object. The corresponding methods in the generic model classes operate on a specific node data type.

RollbackTransaction()

Call the UndoManager's RollbackTransaction method.

bool RollbackTransaction()

Returns

bool

StartTransaction(string)

Call the UndoManager's StartTransaction method.

bool StartTransaction(string tname)

Parameters

tname string

a String describing the transaction

Returns

bool

the value of the call to StartTransaction

Events

Changed

The Changed event is raised whenever the model is modified.

event EventHandler<ModelChangedEventArgs> Changed

Event Type

EventHandler<ModelChangedEventArgs>
See Also
StockSharp.Xaml.Diagram.GXDiagram.Model.ModelChange

See Also

StockSharp.Xaml.Diagram.GXDiagram.Model.ITreeModel
StockSharp.Xaml.Diagram.GXDiagram.Model.IConnectedModel
StockSharp.Xaml.Diagram.GXDiagram.Model.ILinksModel
StockSharp.Xaml.Diagram.GXDiagram.Model.IGroupsModel
StockSharp.Xaml.Diagram.GXDiagram.Model.DiagramModel
GraphLinksModel<NodeType, NodeKey, PortKey, LinkType>
StockSharp.Xaml.Diagram.GXDiagram.Model.GraphModel`2
StockSharp.Xaml.Diagram.GXDiagram.Model.TreeModel`2