Click here to Skip to main content
15,886,724 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 302K   7.4K   185  
An article for anyone interested in how to build an extensible application using WPF and the Model-View-ViewModel pattern.
#region MIT License
/*
 * Copyright (c) 2005-2008 Jonathan Mark Porter. http://physics2d.googlepages.com/
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal 
 * in the Software without restriction, including without limitation the rights to 
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 
 * the Software, and to permit persons to whom the Software is furnished to do so, 
 * subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be 
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */
#endregion



#if UseDouble
using Scalar = System.Double;
#else
using Scalar = System.Single;
#endif
using System;
using System.Collections.Generic;

namespace Physics2DDotNet.Ignorers
{
    /// <summary>
    /// A collection that stores ints that represent groups
    /// </summary>
    [Serializable]
    public class GroupCollection : ICollection<int>
    {
        public static bool Intersect(GroupCollection groups1, GroupCollection groups2)
        {
            List<int> g1 = groups1.groups;
            List<int> g2 = groups2.groups;
            int index1 = 0;
            int index2 = 0;
            while (index1 < g1.Count && index2 < g2.Count)
            {
                if (g1[index1] == g2[index2])
                {
                    return true;
                }
                else if (g1[index1] < g2[index2])
                {
                    index1++;
                }
                else
                {
                    index2++;
                }
            }
            return false;
        }

        List<int> groups = new List<int>();

        public GroupCollection()
        {
            groups = new List<int>();
        }
        public GroupCollection(GroupCollection copy)
        {
            this.groups = new List<int>(copy.groups);
        }

        /// <summary>
        /// Gets the number of collison Groups the ignorer is part of.
        /// </summary>
        public int Count
        {
            get { return groups.Count; }
        }
        bool ICollection<int>.IsReadOnly
        {
            get { return false; }
        }

        /// <summary>
        /// Trys to add a group.
        /// </summary>
        /// <param name="item">The group ID to add.</param>
        /// <returns>false if the ignorer was already part of the group; otherwise false.</returns>
        public bool Add(int item)
        {
            for (int index = 0; index < groups.Count; ++index)
            {
                if (groups[index] == item)
                {
                    return false;
                }
                if (groups[index] > item)
                {
                    groups.Insert(index, item);
                    return true;
                }
            }
            groups.Add(item);
            return true;
        }
        /// <summary>
        /// adds an array of group ids.
        /// </summary>
        /// <param name="array">The array of group IDs. (this will be sorted)</param>
        /// <returns>the number of IDs that were not already part of the group.</returns>
        public int AddRange(int[] array)
        {
            if (array == null) { throw new ArgumentNullException("collection"); }
            Array.Sort(array);
            List<int> newGroups = new List<int>(groups.Count + array.Length);

            int newIndex = 0;
            int oldIndex = 0;
            int index = 0;
            int count = 0;
            while ((newIndex < array.Length) && (oldIndex < groups.Count))
            {
                if (array[newIndex] == groups[oldIndex])
                {
                    oldIndex++;
                }
                else if (array[newIndex] > groups[oldIndex])
                {
                    newGroups.Add(groups[oldIndex]);
                    oldIndex++;
                    index++;
                }
                else
                {
                    newGroups.Add(array[newIndex]);
                    newIndex++;
                    index++;
                    count++;
                }
            }
            for (; newIndex < array.Length; ++newIndex)
            {
                if (index == 0 || newGroups[index - 1] != array[newIndex])
                {
                    newGroups.Add(array[newIndex]);
                    index++;
                    count++;
                }
            }
            for (; oldIndex < groups.Count; ++oldIndex)
            {
                if (index == 0 || newGroups[index - 1] != groups[oldIndex])
                {
                    newGroups.Add(groups[oldIndex]);
                    index++;
                }
            }
            this.groups = newGroups;
            return count;
        }
        /// <summary>
        /// returns true if the ignorer is part of the group.
        /// </summary>
        /// <param name="item">The group ID.</param>
        /// <returns>true if the ignorer is part of the group; otherwise false.</returns>
        public bool Contains(int item)
        {
            return groups.BinarySearch(item) >= 0;
        }
        /// <summary>
        /// returns the number of groups in the array it is part of.
        /// </summary>
        /// <param name="array">The array of group IDs. (this will be sorted)</param>
        /// <returns>The number of groups in the array it is part of.</returns>
        public int ContainsRange(int[] array)
        {
            if (array == null) { throw new ArgumentNullException("collection"); }
            Array.Sort(array);
            int index1 = 0;
            int index2 = 0;
            int count = 0;
            while (index1 < groups.Count && index2 < array.Length)
            {
                if (groups[index1] == array[index2])
                {
                    count++;
                    index1++;
                    index2++;
                }
                else if (groups[index1] < array[index2])
                {
                    index1++;
                }
                else
                {
                    index2++;
                }
            }
            return count;
        }
        /// <summary>
        /// Trys to remove the ignorer from a group.
        /// </summary>
        /// <param name="item">The group ID.</param>
        /// <returns>true if the ignore was part of the group; otherwise false.</returns>
        public bool Remove(int item)
        {
            int index = groups.BinarySearch(item);
            if (index < 0) { return false; }
            groups.RemoveAt(index);
            return true;
        }
        /// <summary>
        /// Trys to remove the ignorer from a range of groups.
        /// </summary>
        /// <param name="array">The array of group IDs. (this will be sorted)</param>
        /// <returns>the number of groups the ignore was removed from.</returns>
        public int RemoveRange(int[] array)
        {
            if (array == null) { throw new ArgumentNullException("collection"); }
            Array.Sort(array);
            int index = 0;
            return groups.RemoveAll(delegate(int value)
            {
                while (index < array.Length)
                {
                    if (value == array[index])
                    {
                        index++;
                        return true;
                    }
                    else if (value > array[index])
                    {
                        index++;
                    }
                    else
                    {
                        return false;
                    }
                }
                return false;
            });
        }
        /// <summary>
        /// returns if the 2 ignores are not part of the same group.
        /// </summary>
        /// <param name="other">the other CollisionGroupIgnorer</param>
        /// <returns>true if they are not part of the same group; otherwiase false.</returns>

        void ICollection<int>.Add(int item)
        {
            Add(item);
        }
        /// <summary>
        /// removes the ignorer from all groups.
        /// </summary>
        public void Clear()
        {
            groups.Clear();
        }
        public void CopyTo(int[] array, int arrayIndex)
        {
            groups.CopyTo(array, arrayIndex);
        }
        public IEnumerator<int> GetEnumerator()
        {
            return groups.GetEnumerator();
        }
        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    }
}

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