X
dnn.blog.
Back

Flexible module design with templates

When you create a module not only for you and for one special portal, you have to decide how to accomplish the multiple design demands your customers have. You can create a fixed design and deal with a lot of classes, so the user can do all the styling with CSS. But in my opinion, this is often not flexible enough. The most flexible solution is in my eyes working with templates and token replace. With this technique you can give your users the widest possible range of possibilities for arranging all the stuff they need in the design they want.

Think of a RSS module where you can style the display of  the news. On one page you want only the headline and date, on another page you need the full text, the date under the text and the headline above… You will never be able to realize all possible combinations with settings like “Show title under text” or “Don’t show headline”

Needed UI elements

In the settings section of your module, you need only a few elements

Template

The user can insert his html-code into the textbox and he can insert the tokens you create for him. It is a good idea to give him some information about these tokens if he clicks the help button :

Helpbutton

And if he struggles give him a “Reset to default” – button where he can reset the template to a default display text!

Generating output

The first thing we need is a placeholder control where you later insert our generated output:

<asp:placeholder id="newsPlaceHolder" runat="server"></asp:placeholder>

In the next step we create a new method in my view control called RenderTemplate. This method receives two parameters:

  • The template text (string)
  • The data object (eg. NewsInfo, POCO object with properties like Title, Link, Description and so on…)
  • Return value is of type Control !
private Control RenderTemplate(NewsInfo news, String template)

In RenderTemplate, we need to replace all our tokens with a string representation of ASP.NET-Controls:

template = template.Replace("[TITLE]", "<asp:label id='\"lblHeadline\"' runat='\"server\"'>");
template = template.Replace("[LINK]", news.Link);
template = template.Replace("[TITLELINK]", "<asp:hyperlink id='\"lnkLink\"' runat='\"server\"'>");
template = template.Replace("[DESCRIPTION]", "<asp:literal id='\"ltrDescription\"' runat='\"server\"' mode='\"PassThrough\"'>");
template = template.Replace("[NEWS]", "<asp:literal id='\"ltrNews\"' runat='\"server\"' mode='\"PassThrough\"'>");
template = template.Replace("[PUBDATE]", "<asp:label id='\"lblPubDate\"' runat='\"server\"'>");
template = template.Replace("[SOURCE]", "<asp:label id='\"lblSource\"' runat='\"server\"'>");</asp:label></asp:label></asp:literal></asp:literal></asp:hyperlink></asp:label>

The next step is very important. Now we make a control of our template string !

Control ctrl = ParseControl(template);

The rest is easy now. We need to find every Control inside of ctrl. If it exists, we set the values (if not, the user hasn’t used the appropriate token)

lblHeadline = FindControlRecursive(ctrl, "lblHeadline") as Label;
if (lblHeadline != null)
	lblHeadline.Text = (TitleLimit > 0 ? ShortenString(news.Title, TitleLimit) : news.Title);

lnkLink = FindControlRecursive(ctrl, "lnkLink") as HyperLink;
if (lnkLink != null)
{
	lnkLink.Text = (TitleLimit > 0 ? ShortenString(news.Title,TitleLimit) : news.Title);
	lnkLink.NavigateUrl = news.Link;
	if (news.Internal == false)
		lnkLink.Target = "_blank";
}

ltrDescription = FindControlRecursive(ctrl, "ltrDescription") as Literal;
if (ltrDescription != null)
	ltrDescription.Text = Server.HtmlDecode((DescriptionLimit > 0 ? ShortenString(news.Description,DescriptionLimit) : news.Description));

ltrNews = FindControlRecursive(ctrl, "ltrNews") as Literal;
if (ltrNews != null)
	ltrNews.Text = Server.HtmlDecode((NewsLimit > 0 ? ShortenString(news.News,NewsLimit) : news.News));

lblPubDate = FindControlRecursive(ctrl, "lblPubDate") as Label;
if (lblPubDate != null)
	lblPubDate.Text = String.Format("{0:" + DateFormat + "}", news.Pubdate);

lblSource = FindControlRecursive(ctrl, "lblSource") as Label;
if (lblSource != null)
{
	Uri url = new System.Uri(news.Link);
	lblSource.Text = url.Host;
}
return ctrl;

At the end we return our generated control ! (TitleLimit, DescriptionLimit, NewsLimit and DateFormat are other setting values. ShortenString is a helper method to cut of a string if it is longer as limit and add some …)

FindControlRecursive is another helper method which iterates recursive through all objects and tries to find the control with the given controlID:

private Control FindControlRecursive(Control rootControl, string controlID)
{
	if (rootControl.ID == controlID)
		return rootControl;

	foreach (Control controlToSearch in rootControl.Controls)
	{
		Control controlToReturn = FindControlRecursive(controlToSearch, controlID);
		if (controlToReturn != null)
			return controlToReturn;
	}
	return null;
}

Last thing we had to do in code behind is to call our RenderTemplate-Method and add our generated control to the placeholder:

string template = "";
if (Settings["Template"] != null)
	template = (string)Settings["Template"];
else
	template = Controller.GetDefaultTemplate();
NewsInfo news = NewsController.GetNews();
Control ctrl = RenderTemplate(News,template);
newsPlaceHolder.Controls.Add(ctrl);

And that is what it looks like (sorry it’s in german…):

Sample Post

Back

about.me.

Torsten WeggenMy name is Torsten Weggen and I am CEO of indisoftware GmbH in Hanover, Germany. I'm into DNN since 2008. Before this, I did a lot of desktop stuff mainly coded with Visual Foxpro (see http://www.auktionsbuddy.de). 

I'm programmer, husband, father + born in 1965.

Please feel free to contact me if you have questions.

Latest Posts

DNN module development with Angular 2+ (Part 7)
6/10/2018 1:43 PM | Torsten Weggen
DNN module development with AngularJS (Part 6)
12/16/2016 7:00 AM | Torsten Weggen
DNN module development with AngularJS (Part 5)
12/16/2016 6:00 AM | Torsten Weggen
DNN module development with AngularJS (Part 4)
12/16/2016 5:00 AM | Torsten Weggen
DNN module development with AngularJS (Part 3)
12/16/2016 4:00 AM | Torsten Weggen
DNN module development with AngularJS (Part 2)
12/16/2016 3:00 AM | Torsten Weggen
DNN module development with AngularJS (Part 1)
12/15/2016 7:19 AM | Torsten Weggen
Blogging in DNN with Markdown Monster by Rick Strahl
11/27/2016 1:14 PM | Torsten Weggen
Creating a global token engine
11/18/2016 10:25 AM | Torsten Weggen
DnnImagehandler - Hot or not ?
2/21/2015 11:52 PM | Torsten Weggen

My Twitter

Torsten Weggen 7/24/2021

@JohannesFinke https://t.co/3WGmhg3eN0 #keinrechterweg

Torsten Weggen 7/24/2021

@RolandHanske @Stefani38312507 @YouTube https://t.co/3WGmhg3eN0 #keinrechterweg

Torsten Weggen 7/24/2021

@zardorak https://t.co/3WGmhg3eN0 #keinrechterweg