Module Builder is probably the best feature that Sitefinity has to offer. In my experience, it's the tool that puts Sitefinity above so many other CMS products.
In addition to being great out of the box, it also has some undocumented features (or less documented, as Sitefinity docs could always use so more content).
The biggest feature you need for really customizing Module Builder is the sf:conditonal tag. It's a gem.
It's also a must of if you really want to customize widgets.
Here's a quick example. Let's stay you created a Module, and you associate related pages to it. Just as a side note, this another great feature of Module Builder, in that you can connect your custom modules to other Sitefinity assets.
Once done, Sitefinity will add a RelatedPages property to your module, and the default widget implementation looks like this:
<div class="sfMultiRelatedItmsWrp">
<h2 class="sfrelatedItmTitle">View More Detail about this Project</h2>
<ul class="sfrelatedList sflist">
<asp:Repeater runat="server" DataSource='<%# Eval("RelatedPages") %>'>
<ItemTemplate>
<li class="sfrelatedListItem sflistitem"><a <%# ((Telerik.Sitefinity.Pages.Model.PageNode)Container.DataItem).OpenNewWindow ? "target=\"_blank\" " : "" %>href='<%# Telerik.Sitefinity.RelatedData.RelatedDataExtensions.GetDefaultUrl(Container.DataItem) %>'><%# Eval("Title") %></a></li>
</ItemTemplate>
</asp:Repeater>
</ul>
</div>
The problem with this is that if there are NO Related Pages, the H2 tag will still display 'Related Pages', even though there are none.
A quick fix is the use the sf:conditional tag, to check to see if ANY Related Pages exist, and if not, display nothing.
Here's the syntax:
<sf:conditional if='<%# (int)Eval("RelatedPages.Count") > 0 %>' runat="server">
<then>
Your code that you want to only be called when Related Pages exist
</then>
</sf:conditional>
That's all there is to it.
You may notice that all of this is ASP.NET WebForms. MVC is a cleaner way to go but I find that not too many people have actually installed Feather yet. If you have installed Feather, you can get Widget Templates in MVC Razor syntax, but that's for another post.
When you working with Web Forms Widget Templates, it's good to remember that you're just in Web Forms land. Not everything in the template is Sitefinity syntax so much as Web Forms syntax.
You'll notice that the asp:Repeater tag is used. You have the full functionality of this tag, which you can also look up at W3Schools.
Yes, Eval statements can be evil, but that's why MVC was invented.
Other Conditional Statements you may try are against strings and other properties in a module.
<sf:conditional if='<%# Eval("ProductName").ToString() == "ProductNameToCheck" %>' runat="server">
<then>
Your code that you want to only be called when the Product Name is equal to ProductNameToCheck
</then>
</sf:conditional>
These conditional statements can be around any block of code, and yes, the else tag also exists. In this example we can check if the Product Name is populated:
<sf:conditional if='<%# Eval("ProductName").ToString().Trim().Length > 0 %>' runat="server">
<then>
Your code that you want to only be called when the Product Name's length is greater than zero
</then>
<else>
Your code that you want to be called when the Product Name's length is zero
</else>
</sf:conditional>
The Eval statement also can help to just figure out what the object type is. You can just Eval RelatedPages and this is displayed:
System.Collections.Generic.List`1[Telerik.Sitefinity.Model.IDataItem]
I took that to mean a List of IDataItems, hence you can use the Count property.