Creating/modifying templates, features and property definitions
In this article, you will learn how to create and modify templates, features and property definitions via the MDK.
Here is a complete example of what is possible with the API. Don't worry if it looks overwhelming. We explore each part in more detail further below:
// new template for entities describing items in a rpg
var item_template = Session.BeginNewObjectTemplate(ObjectType.Entity);
item_template.DisplayName = "Item";
item_template.TechnicalName = "Item";
// a new feature for our item properties
var item_feature = Session.BeginNewFeature();
item_feature.DisplayName = "Basic Item Properties";
item_feature.TechnicalName = "BasicItem";
// a property for the gold value
var gold_property = item_feature.AddProperty<NumberPropertyBlueprint>();
gold_property.DisplayName = "Cost in gold";
gold_property.TechnicalName = "GoldCost";
gold_property.MinimumValue = 0;
gold_property.MaximumValue = 1000;
gold_property.Precision = 2;
gold_property.Unit = "g";
var item_feature_proxy = Session.EndFeature(item_feature);
// add the item feature to our template
item_template.AddFeature(item_feature_proxy);
Session.EndObjectTemplate(item_template);
// create an item with our new template
var broadsword = Session.CreateEntity(Session.GetSystemFolder(SystemFolderNames.Entities), "Broadsword", "Item");
// change the gold cost of our broad sword
broadsword["BasicItem.GoldCost"] = 100.50;Blueprint sessions
Whenever you create or modify an element in articy:draft X's Template Design section, you use a dedicated editor session. This session safely tracks all changes while working on the element. Only once applied, the changes are submitted and the project gets updated. A similar workflow is necessary when working on your Template Design via the MDK:
- First, you need to start a dedicated session, which we call a blueprint session in the MDK. There are blueprint sessions for all Template Design types: Property Definition, Feature, and Template. A session is started by calling the appropriate Begin... method on your ApiSession object, which creates the blueprint session object.
- Next, you use this blueprint object to specify your changes, just like you would in articy:draft X in the dedicated editor session.
- Finally, you apply your changes by invoking the End... method that matches the initially called Begin... method, effectively closing the current blueprint session and updating your project.
Let's consider the following example:
FeatureDescriptorBlueprint sessionFeatureBlueprint = myApiSession.BeginNewFeature();
// work with the blueprint
ObjectProxy myNewFeature = myApiSession.EndFeature(sessionFeatureBlueprint);The process is similar for templates and property definitions:
ObjectTemplateBlueprint sessionTemplateBlueprint = myApiSession.BeginNewObjectTemplate(ObjectType.Entity);
// work with the blueprint
ObjectProxy myNewTemplate = myApiSession.EndObjectTemplate(sessionTemplateBlueprint);PropertyDefinitionBlueprint<NumberPropertyBlueprint> sessionPropertyBlueprint = myApiSession.BeginNewPropertyDefinition<NumberPropertyBlueprint>();
// work with the blueprint
ObjectProxy myNewPropertyDefinition = myApiSession.EndPropertyDefinition(sessionPropertyBlueprint);In all cases, you receive a handle to the actually created / modified object as a ObjectProxy.
Working with features
Let's now have a closer look at specifying new objects. We start with features. Features allow you to group properties into logical sets. These can then be added to templates.
Creating a new feature
Let's create a feature and set the DisplayName and TechnicalName:
var bp_feature = Session.BeginNewFeature();
// lets change the display name and technical name
bp_feature.DisplayName = "My new Feature";
bp_feature.TechnicalName = "My_new_Feature";
Session.EndFeature(bp_feature);
Adding properties to a feature
A feature has little use without additional properties. Properties can be added directly via the feature blueprint session object. All property types that exist in articy:draft X are available in the MDK as well. As we are adding properties to our feature via a blueprint session, the properties added are blueprint objects themselves, tracking the changes until the feature blueprint session ends. Only then they are added as actual properties to the new feature.
var bp_feature = Session.BeginNewFeature();
var bp_num = bp_feature.AddProperty<NumberPropertyBlueprint>();
bp_num.DisplayName = "Cost in Gold";
bp_num.TechnicalName = "GoldCost";
bp_num.MinimumValue = 0;
bp_num.MaximumValue = 100;
bp_num.Precision = 2;
bp_num.Unit = "g";
Session.EndFeature(bp_feature);
- BooleanPropertyBlueprint
- DropDownPropertyBlueprint
- NumberPropertyBlueprint
- QueryStripPropertyBlueprint
- ScriptPropertyBlueprint
- TextPropertyBlueprint.
Property grid: placement and custom layout

When adding properties to a feature, the properties are placed onto a grid in the articy:draft X UI. The properties have different dimensions, not only depending on the type, but also based on meta properties (for example, the height of a boolean property depends on the value of the meta property DisplayAsDropDownList). This is important to consider when you manually place the objects on the grid. Luckily, when you call EndFeature the framework will use the built-in LeftToRightTopToBottomLayout as the default layouter and place your properties automatically.
If this default layout doesn't suit your needs, you can implement a custom layouter by implementing the interface IObjectCustomizationGridLayout and then passing an instance of your class to the EndFeature(FeatureDescriptorBlueprint, IObjectCustomizationGridLayout) call.
public sealed class MyCustomLayouter : IObjectCustomizationGridLayout
{
/// <inheritdoc/>
public bool AllowPartiallySetPositions
{
get { return false; }
}
public void CalculateGridLayout(FeatureDescriptorBlueprint aTargetFeature)
{
foreach (var prop in aTargetFeature.Properties)
{
// do your calculations
int current_x = ...
int current_y = ...;
prop.SetPosition(current_x, current_y);
}
}
}If you wish to manually place properties on the grid, you will find the SetPosition(Int32, Int32) method on a property blueprint.
Modifying existing features
Aside from creating new features, you can also modify existing ones. When you open an existing feature, all properties and their meta properties are copied into corresponding blueprint objects. That way you can read and modify everything accordingly. Note that the blueprint session object keeps track of what was already there and what was changed or added during the session, so you don't have to worry about that. For more details, check Meta Data.
If you want to modify a property within a feature, you can access the property in one of two ways: You can either access it via the C# property Property ...
// get an existing feature
var feature_proxy = Session.GetObjectByTechName("DefaultBasicCharacterFeature");
// modify it in a blueprint session
var bp_feature = Session.BeginModifyFeature(feature_proxy);
// get the text property Appearance and change the default value
bp_feature.Property<TextPropertyBlueprint>("Appearance").DefaultValue = "The person has an average build with unremarkable features.";
// finish the session to update the articy objects.
Session.EndFeature(bp_feature);// get an existing feature
var feature_proxy = Session.GetObjectByTechName("DefaultBasicCharacterFeature");
// modify it in a blueprint session
var bp_feature = Session.BeginModifyFeature(feature_proxy);
// iterate all properties
foreach (var prop in bp_feature.Properties)
{
}
// finish the session to update the articy objects.
Session.EndFeature(bp_feature);Deleting existing features
Deleting a feature can be done in two ways. The first is via the regular object proxy deletion:
var feature_proxy = Session.GetObjectByTechName("DefaultBasicCharacterFeature");
Session.DeleteObject(feature_proxy);var feature_proxy = Session.GetObjectByTechName("DefaultBasicCharacterFeature");
// modify it in a blueprint session
var bp_feature = Session.BeginModifyFeature(feature_proxy);
// mark the feature for removal
bp_feature.MarkForDeletion();
// finish the session to update the articy objects.
Session.EndFeature(bp_feature);Working with template objects
Template objects, or templates for short, are a collection of features associated to a valid object type. Consequently, you can modify the template information and the features it contains using a template blueprint session.
Creating a new template
Let's create a template and set the DisplayName and TechnicalName. Additionally, a template allows you to set an icon and a color:
var bp_template = Session.BeginNewObjectTemplate(ObjectType.Entity);
bp_template.TechnicalName = "Item";
bp_template.DisplayName = "Item";
// set the template color
bp_template.Color = (Color)ColorConverter.ConvertFromString("#8A5B04");
// set an icon
bp_template.UsePngFileAsIcon("sword.png");
Session.EndObjectTemplate(bp_template);
Adding features to a template
Similarly to a feature without properties, a template without features is of little use, so let us explore ways to add features:
// get an existing feature
var feature_proxy = Session.GetObjectByTechName("DefaultBasicCharacterFeature");
// start our blueprint session
var bp_template = Session.BeginNewObjectTemplate(ObjectType.Entity);
// and add a reference to this new feature
var bp_feature_usage = bp_template.AddFeature(feature_proxy);
// and finalize the template creation
Session.EndObjectTemplate(bp_template);Modifying existing templates
You can edit existing templates by providing the object ID or use an ObjectProxy.
var main_character_template_proxy = Session.GetObjectByTechName("DefaultMainCharacterTemplate");
var bp_template = Session.BeginModifyObjectTemplate(main_character_template_proxy);
bp_template.AddFeature("My_Fancy_Feature");
Session.EndObjectTemplate(bp_template);You can also modify certain meta-data on properties through the template layer. To do that, access the desired property using the feature's name to qualify your query. In the example below, we access the Appearance property defined in the DefaultBasicCharacterFeature:
var main_character_template_proxy = Session.GetObjectByTechName("DefaultMainCharacterTemplate");
var bp_template = Session.BeginModifyObjectTemplate(main_character_template_proxy);
// now we access the Appearance text property in the DefaultBasicCharacterFeature in our template
var bp_prop_appearance = bp_template.Property<TextPropertyBlueprint>("DefaultBasicCharacterFeature.Appearance");
bp_prop_appearance.InvalidCharacters = "€$@";
Session.EndObjectTemplate(bp_template);When your template has multiple features, you can also reorder your features, by modifying the SortOrder property.
var main_character_template_proxy = Session.GetObjectByTechName("DefaultMainCharacterTemplate");
var bp_template = Session.BeginModifyObjectTemplate(main_character_template_proxy);
bp_template.Features[0].SortOrder = 1;
bp_template.Features[1].SortOrder = 0;
Session.EndObjectTemplate(bp_template);Assigning templates
While not directly part of the blueprint session and model customization framework, it is worth to revisit how you assign existing templates to your objects.
// our template
var character_template = Session.GetObjectByTechName("DefaultMainCharacterTemplate");
// assign it directly when creating the object
var bob_proxy = Session.CreateEntity(Session.GetSystemFolderId(SystemFolderNames.Entities), "Bob", character_template.GetTemplateTechnicalName());
// create an object without template
var sally_proxy = Session.CreateEntity(Session.GetSystemFolderId(SystemFolderNames.Entities), "Sally");
// assign it later, overriding any previously set templates
// here you can use the ID or TechnicalName and ignore any template color changes
sally_proxy.SetTemplate(character_template.Id, false);Delete existing templates
Deleting a template can be done in two ways. The first is via the regular object proxy deletion:
var template_proxy = Session.GetObjectByTechName("DefaultSupportingCharacterTemplate");
Session.DeleteObject(template_proxy);var template_proxy = Session.GetObjectByTechName("DefaultSupportingCharacterTemplate");
// modify it in a blueprint session
var bp_template = Session.BeginModifyObjectTemplate(template_proxy);
// mark the template for removal
bp_template.MarkForDeletion();
// finish the session to update the articy objects.
Session.EndObjectTemplate(bp_template);Working with property definitions
In most cases it is sufficient to define and modify properties directly in the context of a feature. However, if you want to reuse a property inside one or across several features, you need to create a dedicated Property Definition.
Creating a new property definition
The process is similar to features and templates, but you need to specify the type of this property inside your project. This is done by providing a type argument that extends PropertyBlueprint:
var bp_property_def = Session.BeginNewPropertyDefinition<NumberPropertyBlueprint>();
bp_property_def.Property.DisplayName = "Cost in gold";
bp_property_def.Property.TechnicalName = "GoldPrice";
bp_property_def.Property.Precision = 2;
bp_property_def.Property.Unit = "g";
Session.EndPropertyDefinition(bp_property_def);
Note that the PropertyDefinitionBlueprintTPropertyBlueprint instance you receive by calling BeginNewPropertyDefinitionTPropertyBlueprint wraps the actual Property blueprint.
Modifying property definition
Editing an existing property definition works in the same way as features and templates:
var bp_property_def = Session.BeginModifyPropertyDefinition<NumberPropertyBlueprint>(existing_property_definition_proxy);
// modify your property definition here
Session.EndPropertyDefinition(bp_property_def);Using property definition
After you have created your property definition like above, you can place properties inside features by utilizing the property definition like this:
// get a proxy to our property definition object
var gold_property_definition_proxy = Session.GetObjectByTechName("GoldPrice");
// start a new feature
var bp_feature = Session.BeginNewFeature();
// add properties utilizing our property definition
var bp_gold_stranger = bp_feature.AddPropertyFromDefinition<NumberPropertyBlueprint>(gold_property_definition_proxy);
bp_gold_stranger.DisplayName = "Cost in gold for strangers";
bp_gold_stranger.TechnicalName = "GoldPriceStranger";
var bp_gold_guild_member = bp_feature.AddPropertyFromDefinition<NumberPropertyBlueprint>(gold_property_definition_proxy);
bp_gold_guild_member.DisplayName = "Cost in gold for guild members";
bp_gold_guild_member.TechnicalName = "GoldPriceGuildMember";
// finish the feature and create the articy objects
Session.EndFeature(bp_feature);Deleting existing property definition
Deleting a property definition can be done in two ways. The first is via the regular object proxy deletion:
var property_definition_proxy = Session.GetObjectByTechName("My_Property_definition");
Session.DeleteObject(property_definition_proxy);var property_definition_proxy = Session.GetObjectByTechName("My_Property_definition");
// modify it in a blueprint session
var bp_property_def = Session.BeginModifyPropertyDefinition<NumberPropertyBlueprint>(property_definition_proxy);
// mark the property definition for removal
bp_property_def.MarkForDeletion();
// finish the session to delete the property definition
Session.EndPropertyDefinition(bp_property_def);Details on properties
Some property types are a bit more involved and benefit from further explanation:
Text and script sizes
In the articy:draft X UI Text and Script property types have dedicated properties for each individual size. In the MDK the different sizes are achieved with a setter on the blueprint object.
var bp_feature = Session.BeginNewFeature();
var bp_name = bp_feature.AddProperty<TextPropertyBlueprint>();
bp_name.DisplayName = "Name";
bp_name.TechnicalName = "Name";
// Small text is just a single line of text
bp_name.Size = TextPropertyBlueprint.TextPropertySizes.Small;
var bp_mouse_hover = bp_feature.AddProperty<ScriptPropertyBlueprint>();
bp_mouse_hover.DisplayName = "OnMouseHover";
bp_mouse_hover.TechnicalName = "OnMouseHover";
// Medium script is a half width script field
bp_mouse_hover.Size = ScriptPropertyBlueprint.ScriptPropertySizes.Medium;
var bp_backstory = bp_feature.AddProperty<TextPropertyBlueprint>();
bp_backstory.DisplayName = "Backstory";
bp_backstory.TechnicalName = "Backstory";
// Large text is a full width text field
bp_backstory.Size = TextPropertyBlueprint.TextPropertySizes.Large;
Session.EndFeature(bp_feature);
Drop down
A drop-down property, used when you need a predefined set of values, can be created in two distinct ways. The first is "manually":
var bp_feature = Session.BeginNewFeature();
var bp_drop_down = bp_feature.AddProperty<DropDownPropertyBlueprint>();
bp_drop_down.DisplayName = "Hero Classes";
bp_drop_down.TechnicalName = "Classes";
// manually add each entry
bp_drop_down.AddDropDownEntry("The Barbarian", "Barbarian");
bp_drop_down.AddDropDownEntry("Mage");
bp_drop_down.AddDropDownEntry("Rogue");
bp_drop_down.AddDropDownEntry("Bard");
bp_drop_down.AddDropDownEntry("None", "None", 255);
Session.EndFeature(bp_feature);
The second is via an existing C# enum, this is helpful if you need to make a connection from an API to articy:draft X:
var bp_feature = Session.BeginNewFeature();
var bp_drop_down = bp_feature.AddProperty<DropDownPropertyBlueprint>();
// uses the MDK ObjectType enum to populate our drop-down
bp_drop_down.PopulateFromEnum<Articy.Api.ObjectType>();
Session.EndFeature(bp_feature);Slot and Strip properties
Slot and Strip properties allow you to exactly specify which articy objects can be placed inside of them. Additionally, you can define which templates, if any, are supported. Here you see some examples how to modify the AllowedObjects property via code:
var bp_feature = Session.BeginNewFeature();
// add a new slot property
var slotProp = bp_feature.AddProperty<SlotPropertyBlueprint>();
// by default, everything is set in the Allowed object types property, if you want to start with everything unset
slotProp.OverrideAndUnsetAll();
// we allow entities with any template
slotProp.ModifyObjectTypeReference(ObjectType.Entity).WithAnyTemplate = true;
// we also allow flow fragments but only ones without a template
slotProp.ModifyObjectTypeReference(ObjectType.FlowFragment).WithAnyTemplate = false;
slotProp.ModifyObjectTypeReference(ObjectType.FlowFragment).WithoutTemplate = true;
// and assets are only allowed with the TextureAsset_Template template.
var texture_template = Session.GetObjectByTechName("TextureAsset_Template");
slotProp.ModifyObjectTypeReference(ObjectType.Asset).SpecificTemplates.Value.Add(texture_template.Id);
// also for completion, we ensure that they are only images
slotProp.SupportedAssetTypes = ObjectTypeAssetReferences.Image;
Session.EndFeature(bp_feature);
Blueprint Session objects and meta properties
Session and change tracking
One thing to familiarize yourself with is the concept of change tracking inside the Blueprint Session objects. All properties from the display name of a feature to the minimum value of a number property inside one of your features, are keeping track of their state throughout a blueprint session. When you are just creating new objects, this doesn't matter much, but when you start modifying existing objects, this can become important. Every meta property is represented with special container types. One of them is ObjectCustomizationPropertyValueTValueType. They are implemented with implicit conversions to their managed type counterpart, but you can also access them directly to check if there were changed. More importantly, you can revert session changes, but more on that later.
A helpful little debug visualization in the Visual Studio debugger will show you the state of these meta properties when inspecting the blueprint objects:

Multi language text
Some properties and meta properties allow you to store text in multiple languages. This is done via the BlueprintMultiLanguageText type which works similarly to the aforementioned ObjectCustomizationPropertyValueTValueType type. The difference is that it can store multiple strings mapped to a language. When you store a string directly to it (without providing an explicit language mapping), you effectively set the text of your main language or Content Creation Language (short CCL).
var bp_feature = Session.BeginNewFeature();
// set the displayname in the CCL, Session.GetPrimaryLanguage()
bp_feature.DisplayName = "My new Feature";
bp_feature.DisplayName.Set(Session.GetLanguage("fr"), "Ma nouvelle fonctionnalité";
bp_feature.DisplayName.Set(Session.GetLanguage("de"), "Mein neues Feature");
Session.EndFeature(bp_feature);Reset Value
The effective value of any object customization value (being the value of a property or the value of metadata for a property) follows a chain of value precedence. So lets say you have a number property definition and you have overwritten the Unit meta data property. When you use this property definition inside a feature, Unit meta property is still the value you'd expect (the one from the number property definition), since the value is taken from there. This precedence, sometimes called Layer, starts at the default value of a property and goes up the chain to the template (for the value even to the model). On every layer you could override the value, indicated by the ResetValue button in the articy:draft template editor, being enabled.

// reset the locally override unit and let it fallback to the previous set value
bp_feature.Property<NumberPropertyBlueprint>("GoldCost").Unit.ResetValue();