Extend a Default Diagram Item
- 4 minutes to read
You can create a diagram item descendant with additional properties to extend a default diagram item.
Create and Register Descendants
Create a custom class and inherit it from the required type (DiagramShape, DiagramContainer, DiagramList, DiagramConnector, or DiagramImage):
Make sure that your descendant class has a parameterless constructor.
Call the DiagramItemTypeRegistrator.Register method to register your descendant type and allow its serialization. You should register descendants at application startup.
If the custom item is used in the Diagram Designer or Item Template Designer, it is necessary to also register it in the item static constructor:
public class CustomDiagramShape : DiagramShape { // Descendant properties static CustomDiagramShape() { DiagramControl.ItemTypeRegistrator.Register(typeof(CustomDiagramShape)); } }
Note
The
DiagramControl
registration mechanism uses short type names to register diagram item descendants of custom types. Generic types are registered only by their short names without type parameters.Register a FactoryItemTool that creates your custom item:
var stencil = new DiagramStencil("CustomStencil", "Custom Shapes"); var itemTool = new FactoryItemTool( "CustomShape", () => "Custom Shape", diagram => { CustomDiagramShape customShape = new CustomDiagramShape() { Width = 100, Height = 50 }; return customShape; }, new Size(100, 50), false ); stencil.RegisterTool(itemTool); DiagramToolboxRegistrator.RegisterStencil(stencil);
Define Custom Properties and Enable Their Serialization
The DiagramControl
serializes items and their properties when a user performs the following actions: copy, paste, cut, undo, and redo. The serialization mechanism is also used to save diagrams to a stream or XML document. Mark your custom properties with the XtraSerializableProperty
attribute to enable their serialization:
Handle the DiagramControl.CustomGetSerializableItemProperties event instead if you cannot change your diagram item implementation:
void diagramControl1_CustomGetSerializableItemProperties(object sender, DiagramCustomGetSerializableItemPropertiesEventArgs e) {
e.Properties.Add(TypeDescriptor.GetProperties(typeof(CustomDiagramShape))["DatabaseObjectID"]);
}
You can also handle the DiagramControl.CustomGetEditableItemProperties event to allow users to edit your custom properties in the Properties Panel:
void diagramControl1_CustomGetEditableItemProperties(object sender, DiagramCustomGetEditableItemPropertiesEventArgs e) {
if (e.Item is CustomDiagramShape) {
e.Properties.Add(TypeDescriptor.GetProperties(typeof(CustomDiagramShape))["DatabaseObjectID"]);
}
}
Add Property Descriptors for Custom Properties
The Properties Panel allows users to edit properties that are not defined directly at the diagram item level (for example, when your diagram is bound to a data source and you need to edit source item properties). To do this, handle the DiagramControl.CustomGetEditableItemProperties event and use the CreateProxyProperty
method to create a custom property descriptor.
Assign Type Converters
The Properties Panel uses the Property Grid control to edit properties. This control supports custom TypeConverters that can be assigned to properties of a diagram item descendant. You can use these converters when editable properties are object collections or custom types.
public class CollectionDescriptionConverter : CollectionConverter {
public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes) {
if (value is List<int> list)
return new PropertyDescriptorCollection(list.Select(x => new CustomPropertyDescriptor(Guid.NewGuid().ToString())), new Attribute[] { ... });
return base.GetProperties(context, value, attributes);
}
public override bool GetPropertiesSupported(ITypeDescriptorContext context) => true;
}
public class CustomPropertyDescriptor : PropertyDescriptor { ... }
public class CustomDiagramShape : DiagramShape {
[TypeConverter(typeof(CollectionDescriptionConverter))]
public ObservableCollection<string> _Values { get; set; }
}