Pages

Thursday, January 14, 2010

Declaritively show content in EpiServer

Not sure if this is a new idea (I doubt it - very few things ever are). I'm a big fan of reducing the amount of display logic in code-behind, especially showing and hiding regions of the page dependant on content stored in the CMS. What I wanted was a custom control in which you could declare a list of EpiServer properties which would need to be not empty for the control to render. I bet you've done this kind of thing a thousand times with a standard <asp:placeholder ... /> and code-behind. Here's a self-contained custom control which takes away all your code-behind pain and mess and allows you to just write markup in your .aspx/.ascx:
public class EpiPlaceHolder : PlaceHolder
{
    protected override void OnInit(EventArgs e)
    {
        this.Load += new EventHandler(EpiPlaceHolder_Load);
        base.OnInit(e);
    }

    public string Property
    {
        get;
        set;
    }

    public bool ShowOnFalse
    {
        get;
        set;
    }

    public PageData CurrentPage
    {
        get;
        set;
    }

    void EpiPlaceHolder_Load(object sender, EventArgs e)
    {
        bool isVisible = false;

        if (CurrentPage == null)
        {
            CurrentPage = ((EPiServer.TemplatePage)Page).CurrentPage;
        }

        if (Property != null)
        {
            string propertyName = Property;

            if (propertyName.Contains(","))
            {
                string[] props = propertyName.Split(new char[] { ',' });

                foreach (string prop in props)
                {
                    isVisible = IsVisibleForProperty(prop);

                    if (!isVisible)
                    {
                        break;
                    }
                }
            }
            else
            {
                isVisible = IsVisibleForProperty(propertyName);
            }
        }

        Visible = (ShowOnFalse) ? !isVisible: isVisible;
    }

    private bool IsVisibleForProperty(string propertyName)
    {
        object currentProperty = CurrentPage[propertyName];

        bool isVis = false;
        if (currentProperty != null)
        {
            bool tryParseProperty = false;
            if (bool.TryParse(currentProperty.ToString(), out tryParseProperty))
            {
                isVis = tryParseProperty;
            }
            else
            {
                isVis = true;
            }
        }

        return isVis;
    }
}
Here's how to use it:
<pdp:EpiPlaceHolder ID="EpiPlaceHolder1" runat="server" Property="LeadImage">
    <EPiServer:Property ID="Property2" runat="server" PropertyName="LeadImage" />
</pdp:EpiPlaceHolder>

Randomize a List<T>

Here's another instalment in a sporadic series of useful C# extension methods. This time we return a List in a random order:

public static class ICollectionExtensions
{
/// <summary>
/// Randomizes the specified source.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source">The source.</param>
/// <returns></returns>
public static ICollection<T> Randomize(this ICollection<T> source)
{
Random rng = new Random();

T[] a = new T[source.Count];
source.CopyTo(a, 0);

byte[] b = new byte[a.Length];
rng.NextBytes(b);

Array.Sort(b, a);

return new List<T>(a);
}
}