DMX includes numerous ways in which you can extend its functions. In this article I zoom in on making a custom control appear in the ‘Custom Attributes’ list. An example of usage would be for instance using this to display a dropdown filled with data from some other application and storing the selected value with the document. Let’s have a closer look at making this work.
Custom attributes
DMX keeps a list of custom attributes for each portal defined in DMX_Attributes. The value for an attribute for a particular document is stored in DMX_EntryAttributes. The value is written as NVARCHAR so there are some limitations here (can’t store a huge text block for instance) and you’ll need to (de)serialize. Other than that it is very straightforward. A ‘standard’ custom attribute like ‘String’ will show a textbox in the edit UI and store the value in the aforementioned value table.
A custom custom attribute
For the definition of an attribute you can specify a ‘ControlToLoad’. This is what you think it is. It will load that control in place. Importantly it will expect this control to inherit from DMX.Framework.EntrySettingsBase. This was modeled after DNN’s SettingsBase for those of you familiar with that. So it has a LoadSettings and used to have a ‘UpdateSettings’. The latter is now:
Public Sub WriteToCurrentEntry(ByRef EntryToUpdate As Business.EntryInfo)
Here you are passed by reference the entry currently under edit. Note it has not yet been written to the database! So a new entry has not EntryId assigned yet. This limitation will be lifted when the ‘BeforeSubmit’ and ‘AfterSubmit’ methods are implemented (slated for 04.02.01).
Using LoadSettings
The EntrySettingsBase includes a path to the entry under edit. It can be found through Me.CurrentEntry. So you can retrieve your current value like so:
If Not Page.IsPostBack Then
Try
Dim objEA As EntryAttributeInfo = EntryAttributesController.GetEntryAttribute(Me.CurrentEntry.EntryId, AttributeId)
If Not objEA Is Nothing Then
ddArticle.Items.FindByValue(objEA.Value).Selected = True
Else
ddArticle.Items.FindByValue(_fixedId.ToString).Selected = True
End If
Catch ex As Exception
End Try
End If
Where AttributeId is the ID of your attribute. The above example shows its use in setting the value in a dropdown.
Using ‘WriteToCurrentEntry’
Once the user has filled in all necessary details and goes to the next step in the wizard, the current entry needs to be updated. This is a little bit more complex as asp.net does not use our dropdown any longer and the value is lost. Instead we need to fish it directly out of the post values ourselves:
Dim objEA As EntryAttributeInfo = EntryAttributesController.GetEntryAttribute(Me.CurrentEntry.EntryId, AttributeId)
If objEA Is Nothing Then
If (Not Request.Params(ddArticle.ClientID.Replace("_", ":")) Is Nothing) Or _fixedId > -1 Then
objEA = New EntryAttributeInfo
With objEA
.AttributeId = Settings.AttributeArticleNr
.EntryId = Me.CurrentEntry.EntryId
If _fixedId > -1 Then
.Value = _fixedId.ToString
Else
.Value = Request.Params(ddArticle.ClientID.Replace("_", ":"))
End If
End With
EntryToUpdate.CustomAttributes.Add(objEA)
End If
Else
If Request.Params(ddArticle.ClientID.Replace("_", ":")) Is Nothing OrElse Request.Params(ddArticle.ClientID.Replace("_", ":")) = "-1" Then
EntryAttributesController.DeleteEntryAttribute(Me.CurrentEntry.EntryId, objEA.AttributeId)
Else
objEA.Value = Request.Params(ddArticle.ClientID.Replace("_", ":"))
EntryToUpdate.CustomAttributes.Add(objEA)
End If
End If
As you can see you determine if the value has already been set before. If so use that object. If not create a new one. Once added to the attributes collection it will be put to the database by DMX.
Rolling out
You’ll need to register your attribute with DMX using an SQL script. First you’ll need to give your project a name and register it in the DMX_Addons table. This will ensure that once uninstalled, all related stuff gets ripped out as well.
INSERT INTO {databaseOwner}{objectQualifier}DMX_Addons (
[AddonKey],
[Availability],
[Description],
[Installed],
[Name]
) VALUES (
'ArticleNr',
'All',
'ArticleNrs',
GetDate(),
'ArticleNr'
)
Now we’re ready to add it to the existing portals
INSERT INTO {objectQualifier}DMX_Attributes
([Addon], [EntryTypes], [IsPrivate], [Name], [PortalId], [ValueType], [ViewOrder], [ResourceFile], [ControlToLoad])
SELECT
'ArticleNr', 'File;Hyperlink', 0, 'ArticleNr', p.PortalId, 'Integer', 0, 'DesktopModules/Bring2mind/DMX/Addons/ArticleNr/App_LocalResources/SharedResources', 'Bring2mind\DMX\Addons\ArticleNr\ArticleDD.ascx'
FROM
{databaseOwner}{objectQualifier}Portals p
WHERE
NOT EXISTS
(
SELECT
*
FROM
{databaseOwner}{objectQualifier}Portals q INNER JOIN {objectQualifier}DMX_Attributes ON q.PortalID = {objectQualifier}DMX_Attributes.PortalId
WHERE
({objectQualifier}DMX_Attributes.Addon = 'ArticleNr')
AND ({objectQualifier}DMX_Attributes.Name= 'ArticleNr')
AND (p.PortalId = q.PortalID)
)
Here the addon is called ArticleNr, the control is under a subdir under DMX: Addons/ArticleNr. The SharedResources.ascx.resx has the text for the label and help next to the control in the UI:
<data name="ArticleNr.Text">
<value>Article</value>
</data>
<data name="ArticleNr.Help">
<value>Specifies to which article this item is bound</value>
</data>
The ‘EntryTypes’ is a semicolon separated list of entry types for which the control will show up. In our case it will show up for files and hyperlinks but not for folders (=’Collection’). Finally you might want to add a trigger to the Portals table so that when a portal gets added you automatically add the attribute to the new portal. But that is up to you.
Wrap all this up in a zip with a proper manifest and you have an installable addon for DMX that will display a dropdown upon edit of a document.