Wiki Markup Hyperlinks for WPF or HTML

This article shows an example of a Wiki-inspired markup for embedding hyperlinks in text – and how to render it as WPF and HTML.

When building any kind of content management system, it’s a good idea to give users the ability to add hyperlinks. Many web-based systems either require that the user knows HTML, or provides some kind of toolbar and preview area that lets the user work with the rendered HTML. The bottom line is that the user is still exposed to an HTML editor, and this is where so many problems can occur.

HTML isn’t very useful if the content needs to be displayed away from the web, such as a WPF application. My preferred way of handling this is to use a simplified markup that can be converted to WPF or HTML at render time. The http://en.wikipedia.org/wiki/Help:Wiki_markup is a great example of this.

The following code demonstrates how I’ve allowed my users to add hyperlinks inside a content management system using a simple syntax, and how those hyperlinks can be rendered either on a webpage or inside a WPF application.

Here’s an example of the syntax:
[[ web address | friendly description ]]

Here’s an example in context:
The markup [[http://www.bing.com|Click here for Bing]] would appear as Click here for Bing.

I’ve resisted the temptation of solving this using a Regular Expression, and instead I’m using the much underused string.Split(string[]) method which breaks the source text into chunks whenever an opening or closing bracket are found. I’m then checking for the presence of the bar (|) character to decide if the chunk should be converted to a hyperlink or displayed as-is. The resulting TextBlock is then returned to the caller from where it can be added dynamically to the page.

Here’s the code for WPF. Note that in order for the hyperlink to open when clicked, the RequestNavigate event must be wired up.

private TextBlock ParseHyperlinks(string line)
{
    if (line.Contains("[["))
    {
        var textBlock = new TextBlock { TextWrapping = System.Windows.TextWrapping.Wrap };
        var chunks = line.Split(new string[] { "[[", "]]" }, StringSplitOptions.RemoveEmptyEntries);
        
        foreach(var chunk in chunks)
        {
            if (chunk.Contains("|"))
            {
                var blocks = chunk.Split('|');
                if (blocks.Length == 2)
                {
                    var hyperlink = new Hyperlink();
                    hyperlink.RequestNavigate += Hyperlink_RequestNavigate;
                    hyperlink.NavigateUri = new Uri(blocks[0]);
                    hyperlink.Inlines.Add(blocks[1]);
                    textBlock.Inlines.Add(hyperlink);
                }
                else
                    textBlock.Inlines.Add(chunk);
            }
            else
                textBlock.Inlines.Add(chunk);
        }
        return textBlock;
    }
    else
        return new TextBlock { Text = line, TextWrapping = System.Windows.TextWrapping.Wrap };
}

private void Hyperlink_RequestNavigate(object sender, RequestNavigateEventArgs e)
{
    System.Diagnostics.Process.Start(e.Uri.ToString());
}

The code to convert the same markup into HTML is very similar:

public string ParseHyperlinks(string line)
{
    if (line.Contains("[["))
    {
        var sb = new StringBuilder();
        var chunks = line.Split(new string[] { "[[", "]]" }, StringSplitOptions.RemoveEmptyEntries);

        foreach (var chunk in chunks)
        {
            if (chunk.Contains("|"))
            {
                var blocks = chunk.Split('|');
                if (blocks.Length == 2)
                    sb.Append(string.Format("<a href='{0}'>{1}</a>", blocks[0], blocks[1]));
                else
                    sb.Append(chunk);
            }
            else
                sb.Append(chunk);
        }
        return sb.ToString();
    }
    else
        return line;
}
Advertisements
This entry was posted in Tips and Tricks and tagged , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s