ASP.NET Formatted String Control
Back to ASP.NET Web Forms land! SharePoint includes a handy control, FormattedString, that can be used to render the contents of its child controls as specified in a format string; pretty much what String.Format does. I wanted to do the same with plain old ASP.NET Web Forms, and here’s what I came up with:
[ParseChildren(false)]
[PersistChildren(true)]
[ControlBuilder(typeof(FormattedControlControlBuilder))]
public class FormattedControl : Control
{
public String FormatString { get; set; }
protected override void RenderChildren(HtmlTextWriter writer)
{
if (String.IsNullOrWhiteSpace(this.FormatString) == false)
{
var list = new List<String>();
var builder = new StringBuilder();
var sw = new StringWriter(builder);
var hw = new HtmlTextWriter(sw);
foreach (var control in this.Controls.OfType<Control>())
{
control.RenderControl(hw);
list.Add(builder.ToString());
builder.Clear();
}
writer.Write(this.FormatString, list.ToArray());
}
else
{
base.RenderChildren(writer);
}
}
}
public class FormattedControlControlBuilder : ControlBuilder
{
public override Boolean AllowWhitespaceLiterals()
{
return false;
}
}
Key points are:
- FormattedControl will not render as default, instead, it will capture the output of all of its child controls into a list and pass it as a parameter to the FormatString string, as {0}, {1}, etc;
- ParseChildrenAttribute and PersisteChildrenAttribute are used to tell ASP.NET how to treat the controls declared inside FormattedControl;
- The ControlBuilderAttribute is used to declare a custom control builder; this custom builder just tells ASP.NET to ignore whitespaces inside the control’s tag, otherwise, we would get a LiteralControl for each tab / space / return character present inside the FormattedControl’s tag, together with those controls explicitly declared.
An example:
<my:FormattedControl runat="server" FormatString="{1}, {0}!">
<asp:Literal runat="server" Text="World"/>
<asp:Literal runat="server" Text="Hello"/>
</my:FormattedControl>
Of course, you should only use FormattedControl with controls that return string literals, otherwise, you will probably get a lot of garbage in the output.