Click here to Skip to main content
15,897,704 members
Articles / Desktop Programming / WPF

Building an Extensible Application with MEF, WPF, and MVVM

Rate me:
Please Sign up or sign in to vote.
4.88/5 (45 votes)
15 Nov 2009LGPL316 min read 303.5K   7.4K   185  
An article for anyone interested in how to build an extensible application using WPF and the Model-View-ViewModel pattern.
using NLog.LayoutRenderers;
using System.Text;
using NLog.Config;
using System.Globalization;
using System;

namespace NLog.Layouts
{
    /// <summary>
    /// A specialized layout that supports header and footer.
    /// </summary>
    [Layout("LayoutWithHeaderAndFooter")]
    public class LayoutWithHeaderAndFooter : ILayout, ILayoutWithHeaderAndFooter
    {
        private ILayout _header = null;
        private ILayout _footer = null;
        private ILayout _layout = null;

        /// <summary>
        /// Initializes a new instance of the <see cref="LayoutWithHeaderAndFooter"/> class.
        /// </summary>
        public LayoutWithHeaderAndFooter()
        {
        }

        /// <summary>
        /// Main layout (can be repeated multiple times)
        /// </summary>
        /// <value></value>
        public ILayout Layout
        {
            get { return _layout; }
            set { _layout = value; }
        }

        /// <summary>
        /// Header
        /// </summary>
        /// <value></value>
        public ILayout Header
        {
            get { return _header; }
            set { _header = value; }
        }

        /// <summary>
        /// Footer
        /// </summary>
        /// <value></value>
        public ILayout Footer
        {
            get { return _footer; }
            set { _footer = value; }
        }

        /// <summary>
        /// Renders the layout for the specified logging event by invoking layout renderers.
        /// </summary>
        /// <param name="logEvent">The logging event.</param>
        /// <returns>The rendered layout.</returns>
        public string GetFormattedMessage(LogEventInfo logEvent)
        {
            return _layout.GetFormattedMessage(logEvent);
        }

        /// <summary>
        /// Returns the value indicating whether a stack trace and/or the source file
        /// information should be gathered during layout processing.
        /// </summary>
        /// <returns>
        /// 0 - don't include stack trace<br/>1 - include stack trace without source file information<br/>2 - include full stack trace
        /// </returns>
        public int NeedsStackTrace()
        {
            int max = Layout.NeedsStackTrace();
            if (Header != null)
                max = Math.Max(max, Header.NeedsStackTrace());
            if (Footer != null)
                max = Math.Max(max, Footer.NeedsStackTrace());
            return max;
        }

        /// <summary>
        /// Returns the value indicating whether this layout includes any volatile
        /// layout renderers.
        /// </summary>
        /// <returns>
        /// 	<see langword="true"/> when the layout includes at least
        /// one volatile renderer, <see langword="false"/> otherwise.
        /// </returns>
        /// <remarks>
        /// Volatile layout renderers are dependent on information not contained
        /// in <see cref="LogEventInfo"/> (such as thread-specific data, MDC data, NDC data).
        /// </remarks>
        public bool IsVolatile()
        {
            if (Layout.IsVolatile())
                return true;

            if (Header != null && Header.IsVolatile())
                return true;

            if (Footer != null && Footer.IsVolatile())
                return true;

            return false;
        }

        /// <summary>
        /// Precalculates the layout for the specified log event and stores the result
        /// in per-log event cache.
        /// </summary>
        /// <param name="logEvent">The log event.</param>
        /// <remarks>
        /// Calling this method enables you to store the log event in a buffer
        /// and/or potentially evaluate it in another thread even though the
        /// layout may contain thread-dependent renderer.
        /// </remarks>
        public void Precalculate(LogEventInfo logEvent)
        {
            Layout.Precalculate(logEvent);
            if (Header != null)
                Header.Precalculate(logEvent);
            if (Footer != null)
                Footer.Precalculate(logEvent);
        }

        /// <summary>
        /// Initializes the layout.
        /// </summary>
        public void Initialize()
        {
            Layout.Initialize();
            if (Header != null)
                Header.Initialize();
            if (Footer != null)
                Footer.Initialize();
        }

        /// <summary>
        /// Closes the layout.
        /// </summary>
        public void Close()
        {
            Layout.Close();
            if (Header != null)
                Header.Close();
            if (Footer != null)
                Footer.Close();
        }

        /// <summary>
        /// Add this layout and all sub-layouts to the specified collection..
        /// </summary>
        /// <param name="layouts">The collection of layouts.</param>
        public void PopulateLayouts(LayoutCollection layouts)
        {
            layouts.Add(this);
            Layout.PopulateLayouts(layouts);
            if (Header != null)
                Header.PopulateLayouts(layouts);
            if (Footer != null)
                Footer.PopulateLayouts(layouts);
        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The GNU Lesser General Public License (LGPLv3)


Written By
Engineer
Canada Canada
By day I'm a Professional Engineer, doing .NET, VB6, SQL Server, and Automation (Ladder Logic, etc.) programming.

On weekends I write and maintain an open source extensible application framework called SoapBox Core.

In the evenings I provide front line technical support for moms4mom.com and I help out with administrative tasks (like formatting stuff). I also pitch in as a moderator from time to time.

You can follow me on twitter.

Comments and Discussions