Working with Related Dynamic Content Items in Sitefinity

Working with Related Dynamic Content Items in Sitefinity

Posted on May 29, 2013 0 Comments

The content you're reading is getting on in years
This post is on the older side and its content may be out of date.
Be sure to visit our blogs homepage for our latest news, updates and information.

This blog post can serve as a successor of the one Rado wrote a year ago on the same subject. However, there have been many improvements in the Module Builder and Sitefinity Thunder since then that will allow us to accomplish the task much easier. I hope it can be seen as a complete guide of how to work with related dynamic content items.

For the purpose of this blog, I have created a new content type called Apps. As starter, it includes just a few fields: Title, Description and ImageGallery


Figure: initial definition of the App module.

The module is active and working just fine. Now let’s add some additional functionality to it – ability to select related items (related Apps). The goal is to easily create relationships between the items (apps) so that any app can have zero, one or more related apps. That’s a common requirement, right? So let’s get started.

1. Create the dynamic content item selector with Sitefinity Thunder

First, we need to create the interface that will allow us to *select* the related apps. Thankfully, Sitefinity Thunder can generate all the code for us. Just go to your solution in Visual Studio, right click the SitefinityWebApp project and select Add > New Item. In the left pane, under your favourite language (C# or VB) select the Sitefinity category. Choose “Sitefinity Dynamic Items Field Control Selector” from the right.

Figure: adding a new dynamic items field control selector to your project.

Let’s call this file RelatedAppsControlSelector. Click add. If you’ve already installed Thunder to this project it will find all the existing dynamic modules and you can select the one you need. We select the App content type in this case:

Figure: Sitefinity Thunder successfully identified all the active dynamic module types in my project.

Sitefinity Thunder will then create a whole bunch of files for us:


Figure: Sitefinity Thunder generates all the files needed for the selector to work properly

 

Those files will take care of the interface for selecting related items and persisting the data in the database. Rebuild the project in Visual Studio so that the logic in those files is included in the output assembly.

2. Modify the content type to include the Related apps field

We need a field in our App module that will store information about the related apps. The one to do the job is of type Array of GUIDs (as we want to support multiple related items). Next we need to select what interface we are going to use to select the related apps. Here we enter the type of the class we added in step 1. 
AddingRelatedAppsField

Figure: Adding the RelatedApps field to the dynamic content type.

Note the value of the “Type or Virtual pat of the custom widget” field – it should contain the full path to the class that was created in step 1. Since I placed it into the ~/custom/fields/ folder I have SitefinityWebApp.Custom.Fields.RelatedAppsControlSelector in the type name.

Continue then Save and finally check the Update Widget Template option:

6. UpdateWidgetTemplate

Figure: update the widget template of the Apps so that it reflects the changes in the module structure

Now let’s go back to Content > Apps and add some items. You’ll see the Add Items button which opens up a modal window with a list of the existing apps. Very consistent with the rest of the UI in the backend. And all this without writing a single line of code!!

SelectingRelatedApp

Figure: adding related items in dynamic content types is easy as cake

Now, let’s look how those apps look in the frontend:

8. FrontEndRelatedApps

Figure: The out-of-the-box widget template is unable to show the related apps

Not the result we are expecting, right? The reason is because the RelatedApp field stores GUID numbers of the related apps so we need a way to find the real apps behind the GUIDs and show the relevant information. To do so, we are going to override the default Full Details widget template and provide our own implementation of it.

 

3. Overriding the Full App Content widget template.

Create a new Web User Control in Visual Studio – I called it FullAppDetails.ascx and placed it under the ~/custom/templates folder.

Paste the following code inside of it:

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="FullAppDetails.ascx.cs" Inherits="SitefinityWebApp.Custom.Templates.FullAppDetails" %>
<%@ Register Assembly="Telerik.Sitefinity" Namespace="Telerik.Sitefinity.DynamicModules.Web.UI.Frontend" TagPrefix="sf" %>
<%@ Register Assembly="Telerik.Sitefinity" Namespace="Telerik.Sitefinity.Web.UI.Fields" TagPrefix="sf" %>
<%@ Register Assembly="Telerik.Sitefinity" Namespace="Telerik.Sitefinity.Web.UI" TagPrefix="sf" %>
<sf:DynamicDetailContainer id="detailContainer" runat="server">
    <LayoutTemplate>
        <div class="sfitemDetails">
            <sf:SitefinityLabel ID="mainShortTextFieldLiteral" runat="server" Text='<%# Eval("Title") %>' WrapperTagName="h1" HideIfNoText="true" CssClass="sfitemTitle" />
            <sf:FieldListView ID="PublicationDate" runat="server" Format="{PublicationDate.ToLocal():MMM d, yyyy, HH:mm tt}" WrapperTagName="div" WrapperTagCssClass="sfitemPublicationDate" />
            <sf:SitefinityLabel ID="SitefinityLabel1" runat="server" Text='<%# Eval("Description")%>' WrapperTagName="div" HideIfNoText="true" CssClass="sfitemLongText" />
            <sf:ImageAssetsField ID="ImageAssetsField1" runat="server" DataFieldName="AppImageGallery" IsThumbnail="False" />
            <sf:AssetsField ID="AssetsField1" runat="server" DataFieldName="AppVideoGallery" />
             
            <telerik:RadListView ID="relatedAppsListView" runat="server"
                    ItemPlaceholderID="ItemsContainer"
                    EnableEmbeddedSkins="false"
                    OnNeedDataSource="relatedAppsListView_NeedDataSource"
                    EnableEmbeddedBaseStylesheet="false">
                <EmptyDataTemplate>
                    <%--<div>No Related Apps</div>--%>
                </EmptyDataTemplate>
                <LayoutTemplate>
                    RELATED APPS:
                    <ul class="sflistList">
                        <asp:PlaceHolder ID="ItemsContainer" runat="server" />
                    </ul>
                </LayoutTemplate>
                <ItemTemplate>
                    <li>
                        <h3>
                            <a href='<%# Eval("UrlName") %>'  ><%# Eval("Title") %></a>
                        </h3>                       
                    </li>
                </ItemTemplate>
            </telerik:RadListView>
        </div>
    </LayoutTemplate>
</sf:DynamicDetailContainer>
<asp:PlaceHolder ID="socialOptionsContainer" runat="server"></asp:PlaceHolder>

Note the RadListView control we’ve added – it will show the related apps in more appropriate way. We just need to bind the list view with data – this is done in the NeedDataSource event:

protected void relatedAppsListView_NeedDataSource(object sender, Telerik.Web.UI.RadListViewNeedDataSourceEventArgs e)
{
    RadListView relatedAppsListView = sender as RadListView;
 
    DynamicModuleManager dynamicModuleManager = DynamicModuleManager.GetManager();
    Type appType = TypeResolutionService.ResolveType("Telerik.Sitefinity.DynamicTypes.Model.Apps.App");
 
    DynamicContent app = ((DetailItem)relatedAppsListView.Parent).DataItem as DynamicContent;
 
    //the array of GUIDs of the related apps
    Guid[] relatedAppsIDs = app.GetValue("RelatedApps") as Guid[];
 
    //a list that will hold the related apps
    List<DynamicContent> relatedAppsCollection = new List<DynamicContent>();
 
    for (int i = 0; i < relatedAppsIDs.Length; i++)
    {
        //get the related app
        DynamicContent relatedApp = dynamicModuleManager.GetDataItem(appType, relatedAppsIDs[i]);
 
        //add it to the list
        relatedAppsCollection.Add(relatedApp);
    }
 
    relatedAppsListView.DataSource = relatedAppsCollection;
}

Build the project and go to the backend. We should tell the widget to use this particular template in the front end. To do so, edit the page where the widget is placed and edit the widget itself. Go to Advanced > ControlDefinition > Views > DynamicContentDetailView and find the TemplatePath field. Enter the relative full path to the user control created above, e.g. ~/Custom/Templates/FullAppDetails.ascx and Save.

Now go to the details of any of the apps and you’ll see something like this:

9. RelatedAppsFrontEnd
Figure: the details page now shows the related apps

Veselin Vasilev

View all posts from Veselin Vasilev on the Progress blog. Connect with us about all things application development and deployment, data integration and digital business.

Comments

Comments are disabled in preview mode.
Topics

Sitefinity Training and Certification Now Available.

Let our experts teach you how to use Sitefinity's best-in-class features to deliver compelling digital experiences.

Learn More
Latest Stories
in Your Inbox

Subscribe to get all the news, info and tutorials you need to build better business apps and sites

Loading animation