WebIconProvider

by jrummell 21. August 2008 22:11

How do you handle sharing icon sets across your web projects?  I started out with an icon folder in each project.  Keeping folders up to date was a bit of a pain - having to remember to update each change across all projects.  Eventually I moved the icons into a class library and compiled them as web resources.  This was great because I could access them from any web project.  But then I wanted to use a different icon set for one project.  I could have just replaced the library icons with the new set, but I didn't want the new set for all of web projects.  All of my projects use the same kinds of icons, e.g. save, edit, delete, new, comment, etc.  So then it hit me, "What if I had an icon set interface that could be used to plug in any number of different icon sets?"

 

Provider Model

The Provider Model seemed like the logical approach.  I had already worked with it when creating custom Membership and Role providers, as well as a SiteMap provider.  The great thing about the provider model is that you can swap providers without recompiling and even do it at runtime.  Here's a class diagram of my provider implementation.

Provider Classes

Following the provider model, I have the following four classes:

WebIconProvider is the abstract icon ProviderBase class that does most of the heavy lifting.  The most important method here is GetImageUrl(WebIcon icon). This an abstract method that returns the url of an image based on the given WebIcon enum value.  WebIcon contains all of the required image types (save, edit, delete, new, comment, etc).

WebIconProviderCollection is a strongly typed collection of WebIconProviders.

WebIconService is a static class that gives access to the providers and a few methods that perform operations using the default provider.

WebIconSection is the ConfigurationSection implementation that contains the configuration settings required for WebIconProviders.

 

WebIconProvider

Now the next step is to implement WebIconProvider.  After implementing it with a few different icon sets, I realized I could refactor out two more abstract classes.

WebIconProvider Classes 

FileWebIconProvider is a virtual path based implementation that provides an ImagePath property that is set in the provider's configuration.  The implementing class must provide the filename of each WebIcon image when it implements WebIconProvider.GetImageUrl(WebIcon icon).

ResourceWebIconProvider is a WebResource implementation that provides a static GetImageUrl(Type type, string resourceName) method that handles retrieving the web resource url.  The implementing class must provide an implementation of IIconResources in it's constructor.  IIconResources is an interface that defines a web resource url for each WebIcon enum value.  ResourceWebIconProvider also provides an implementation of WebIconProvider.GetImageUrl(WebIcon icon) that maps WebIcon values to the appropriate IIconResources property.

 

ResourceWebIconProvider

FileWebIconProvider is pretty much self explanatory.  Creating a new ResourceWebIconProvider icon set is also fairly simple.  First you need to pick out your icons! A few free sets that I like are Silk Icons, Sancons, and ASP.Net Icons. Then you'll need to add them to a class library project and set their build action to Embedded Resource.  The next step is to implement IIconResources.

    /// <summary>
    /// The SilkIcon implementation of <see cref="IIconResources"/>.
    /// </summary>
    internal struct SilkIconResources : IIconResources
    {
        private const string __baseResourcePath = "SilkIcons.Icons.";
        internal const string _Add = __baseResourcePath + "add.png";
        internal const string _Calendar = __baseResourcePath + "calendar.png";
        internal const string _Check = __baseResourcePath + "tick.png";
        
        /* snip */
 
        private static readonly SilkIconResources _default = new SilkIconResources();
 
        /// <summary>
        /// Gets the default instance.
        /// </summary>
        /// <value>The default instance.</value>
        public static IIconResources Default
        {
            get { return _default; }
        }
 
        #region IIconResources Members
 
        public string Add
        {
            get { return _Add; }
        }
        
        public string Calendar
        {
            get { return _Calendar; }
        }
 
        public string Check
        {
            get { return _Check; }
        }
        
        /* snip */
 
        #endregion
    }

The next step is adding the WebResourceAttributes.  ContentType is a struct with string constants that contain the valid web resource content types, such as "image/png".

[assembly: WebResource(SilkIconResources._Edit, ContentType.Png)]
[assembly: WebResource(SilkIconResources._Delete, ContentType.Png)]
[assembly: WebResource(SilkIconResources._Add, ContentType.Png)]
[assembly: WebResource(SilkIconResources._Calendar, ContentType.Png)]
        /* snip */

The final step is implementing ResourceWebIconProvider, which is only a few lines of code.

    /// <summary>
    /// A <see cref="WebIconProvider"/> for Silk Icons (http://www.famfamfam.com/lab/icons/silk/).
    /// </summary>
    public class SilkIconProvider : ResourceWebIconProvider
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="SilkIconProvider"/> class.
        /// </summary>
        public SilkIconProvider()
            : base(SilkIconResources.Default, "Mark James", "http://www.famfamfam.com/lab/icons/silk/")
        {
        }
    }

WebControls

I also created a few WebControls to make displaying the icons easier.

Control Classes

WebIconImage is a control that inherits Image and adds a couple WebIconProvider related properties. You can use it just like an <asp:Image> except that you can specify the icon you want to display and it uses a WebIconProvider to determine the url.  The following markup would display the default WebIconProvider's help image.

<webicons:WebIconImage id="WebIconImage1" icon="Help" runat="server" />

 

WebIconCredit is control that displays the name of the icon set creator and a link to the creator's web site.  The name and link come from the configuration settings.  This control's markup is very simple.

<webIcons:WebIconCredit ID="WebIconCredit1" runat="server" />

 

Configuration

The configuration looks a lot like any provider configuration.

    <webIcons defaultProvider="Silk">
        <providers>
            <add name="Sanscons"
                 type="Sanscons.SansconsIconProvider, Sanscons"
                 cssClass="icon"/>
            <add name="Silk"
                 type="SilkIcons.SilkIconProvider, SilkIcons"/>
        </providers>
    </webIcons>

 

Source Code

The following zip file contains four WebIconProvider implementations and a test web site.

WebIcons.zip (2.18 mb)

Tags: ,

asp.net

Comments

12/13/2008 7:34:44 AM #

Cohen

I love the implementation architecture... I am actually looking to develop something like a "repository selector" (by lack of a better naming), and your architecture might fit it.

What I am curious about:
the SilkIconResources is defined as a struct which you then use as a singleton (returning the instance through a static property).
This seems a bit strange... because it will result in lots of instances in memory, which I suppose you wanted to prevent defining it as a singleton (by definition only one instance).

Cohen Belgium

12/14/2008 6:16:38 PM #

jrummell

@Cohen

Glad you like the architecture, thanks.

I'm not sure what you mean about SilkIconResources. I intentionally defined it as a singleton. How does that result to multiple instances in memory if the only instance referenced is SilkIconResources.Default?  Does it have to with it being a struct instead of class?

jrummell United States

Comments are closed

Powered by BlogEngine.NET 1.5.0.7
Theme by Mads Kristensen | Modified by Mooglegiant

About the author

John is a .Net Web Developer for a manufacturing company in Ohio. In his free time he enjoys web development, the outdoors, and spending time with his wife.

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in  anyway.

© Copyright 2009

Ads By Google