The Sitefinity Module builder allows you to create custom types on the fly for use as custom modules.
In the 5.0 release back in February, a two new field types were added to the module builder: Guid and Array of Guids. These allow you to "link" content items using their Id properties, adding support of one-to-many and many-to-many relationships between your content.
Radoslav posted a helpful sample of a custom dynamic content selector field control that allows you to select content for these relationships. While this sample is thorough, it is a lot of custom code to work with if you simply want to make a basic association.
Such a situation occurs with the recently released Sitefinity MVC Store sample project. In this project, there are two content types Artist and Genre that are referenced in a one-to-many relationship to the content type Album. Instead of implementing the full selector above, a simpler control was created by inheriting from the existing ChoiceField control.
This field already contains a lot of the functionality required, since it was designed to present a list of options to the user, in many forms. In this case, the field is defaulted to a dropdown list:
In this example, the name of the field (Artist and Genre exactly match the name of the Content Type being associated. This eliminates the need to create a separate field for each content type, and it can even be reused in other content modules.
Here is the full code for this custom field control, showing how this was achieved.
View Code Sample on Gist
Keeping the Default Behavior
Notice that not only does this control inherit from ChoiceField but the ScriptDescriptorType and ResourcesAssemblyInfo overrides also force this control to reuse the base behavior of that field. The reason for this is that by doing so, the control will reuse the native JavaScript file for the designer, so that it isn't necessary rewrite a entirely new script from scratch just to accommodate our custom type. Instead, the default one for ChoiceField is compatible since this control inherits directly from it.
Defining the Desired Behavior
Also, you can see that the RenderChoicesAs property forces a list. This could be modified if you a different input type is required. However, using a custom field does not present the option to set this on the website when the field is added, so it is explicitly set here.
Populating the Choice Collection
Finally, the Configure method takes care of actually loading the choices and presenting them to the user. While you can certainly hard-code your custom module and content types into the control, the FieldDefinition that is passed to this method includes a lot of information that can be used to extract the data needed to load the content items.
The ControlDefinitionName contains the type of the current content type using dot notation (Example: Telerik.Sitefinity.DynamicTypes.Model.MusicStore.Album), so removing the last element results in the parent module type.
NOTE: This selector does not account for nested or child types, and should be modified if you are using such a content type.
The name of the field is stored in the FieldName property, and appending them together results in the full name of the dynamic content type.
This name can then be used to initialize the Content Type required by the Dynamic Module Manager to retrieve content items of that type. From there a simple use of the Sitefinity API retrieves the published items and binds them to the Choices collection so they can be shown in the dropdown list.
Retrieving Associated Items Using the API
Once your content items are added with these associations using the new custom field, you can easily retrieve them back using the API. This is demonstrated in the Browse method of the StoreController.cs class:
View Code Sample on Gist
Which reveals the albums which match the selected Genre:
Enjoyed this post and/or found it useful?