Skip to content

Instantly share code, notes, and snippets.

@hugoware
Created April 7, 2010 03:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hugoware/358458 to your computer and use it in GitHub Desktop.
Save hugoware/358458 to your computer and use it in GitHub Desktop.
Uses WebControls to allow content to be written to multiple areas on the same view using ASP.NET MVC
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.UI;
namespace MvcWebControls {
/// <summary>
/// Creates a zone that writes content to the matching ContentArea
/// </summary>
public class ContentArea : TemplateControl {
#region Constants
private const string CONTENT_AREA_CONTAINER = "AreaContainers";
#endregion
#region Constructors
/// <summary>
/// Creates a new ContentArea that allows you to write content to ContentDisplayAreas
/// </summary>
public ContentArea() {
ContentArea._Areas.Add(this);
}
#endregion
#region Properties
/// <summary>
/// The name of the content marker to write content to
/// </summary>
public string Target { get; set; }
#endregion
#region Shared Information
//returns a list of content areas for the page
internal static List<ContentArea> _Areas {
get {
//attempt to find the container and create a
//new one if it hasn't been found yet
List<ContentArea> containers =
HttpContext.Current.Items[CONTENT_AREA_CONTAINER] as List<ContentArea>;
if (containers == null) {
containers = new List<ContentArea>();
HttpContext.Current.Items[CONTENT_AREA_CONTAINER] = containers;
}
//return the generated container
return containers;
}
}
//gets the content for this control
internal LiteralControl _GetContent() {
//write the content to a string
using (StringWriter output = new StringWriter()) {
using (_ContentAreaWriter html = new _ContentAreaWriter(output)) {
//write the content
base.Render(html);
//create the content and return it as a control
string content = output.ToString();
return new LiteralControl(content);
}
}
}
#endregion
#region Handling Events
//do not render these areas
protected override void Render(HtmlTextWriter writer) {
if (!(writer is _ContentAreaWriter)) { return; }
base.Render(writer);
//don't actually ever render this to
//the real HTML writer
//base.Render(writer);
}
#endregion
#region Helper Classes
private class _ContentAreaWriter : HtmlTextWriter {
public _ContentAreaWriter(TextWriter writer) : base(writer) { }
}
#endregion
}
/// <summary>
/// Consumes content written into markers
/// </summary>
[ParseChildren(true)]
[PersistChildren(false)]
public class ContentDisplayArea : Control {
#region Properties
/// <summary>
/// Should this accepts any targets even if the case of
/// the names do not match
/// </summary>
public bool IgnoreCase { get; set; }
/// <summary>
/// Ignores ContentAreas that have matching IDs
/// </summary>
public bool IgnoreDuplicates { get; set; }
#endregion
#region Constructors
/// <summary>
/// Creates a new area to write content to
/// </summary>
public ContentDisplayArea() {
}
#endregion
#region Handling Events
//handles finding the correct areas to render
protected override void Render(HtmlTextWriter writer) {
this.ID = this.ID ?? string.Empty;
//get the correct way to handle case
StringComparison compare = this.IgnoreCase
? StringComparison.OrdinalIgnoreCase
: StringComparison.Ordinal;
//get a list of IDs to track
List<string> added = new List<string>();
//add all of the controls that exist for this page
foreach (ContentArea area in ContentArea._Areas) {
if (!this.ID.Equals(area.Target, compare)) { continue; }
//check the IDs for duplicates
if (this.IgnoreDuplicates &&
!string.IsNullOrEmpty(area.ID) &&
added.Any(item => item.Equals(area.ID, compare))) {
continue;
}
//add the ID of the items checked
if (area.ID is string) {
added.Add(area.ID ?? string.Empty);
}
//add each of the child controls
this.Controls.Add(area._GetContent());
//No need to hide controls since ContentAreas
//aren't actually ever rendered
//area.Controls.Clear();
}
//finally, render the control normally
base.Render(writer);
}
#endregion
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment