AlphaNumericComparer.cs 5.58 KB
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.Windows.Forms;

namespace MoyaAdminLib
{
    public class AlphaNumericComparer : IComparer
    {
        public int ColumnIndex;
        public bool SortOrderDesc;
        public Type SortOrderType;

        public AlphaNumericComparer()
        {
            ColumnIndex = 0;
        }

        public AlphaNumericComparer(int column)
        {
            ColumnIndex = 0;
        }

        public AlphaNumericComparer(int column, bool sortOrderDesc) 
		{
				this.SortOrderDesc = sortOrderDesc;
				ColumnIndex=column;
        }

        public AlphaNumericComparer(int column, bool sortOrderDesc, Type type)
        {
            this.SortOrderDesc = sortOrderDesc;
            ColumnIndex = column;
            this.SortOrderType = type;
        }

        public int Compare(object x, object y)
        {
            string s1 = null;
            string s2 = null;

            if (x != null)
            {
                if (x is ListViewItem)
                {
                    ListViewItem lvix = (ListViewItem)x;
                    if (ColumnIndex < lvix.SubItems.Count)
                        s1 = lvix.SubItems[ColumnIndex].Text;
                    else
                        return 0;
                }
            }

            if (s1 == null)
                return 0;

            if (y != null)
            {
                if (y is ListViewItem)
                {
                    ListViewItem lviy = (ListViewItem)y;
                    if (ColumnIndex < lviy.SubItems.Count)
                        s2 = lviy.SubItems[ColumnIndex].Text;
                    else
                        return 0;
                }
            }

            if (s2 == null)
                return 0;

            

            decimal num1 = 0;
            decimal num2 = 0;

            if (SortOrderType != null)
            {
                if (SortOrderType == typeof(DateTime))
                {
                    DateTime date1 = DateTime.MinValue;
                    DateTime date2 = DateTime.MinValue;

                    if (DateTime.TryParse(s1, out date1) && DateTime.TryParse(s2, out date2))
                        return Compare(date1, date2);
                }
            }

            if (Decimal.TryParse(s1, out num1) && Decimal.TryParse(s2, out num2))
            {
                return Compare(num1, num2);
            }

            int len1 = s1.Length;
            int len2 = s2.Length;
            int marker1 = 0;
            int marker2 = 0;

            // Walk through two the strings with two markers.
            while (marker1 < len1 && marker2 < len2)
            {
                char ch1 = s1[marker1];
                char ch2 = s2[marker2];

                // Some buffers we can build up characters in for each chunk.
                char[] space1 = new char[len1];
                int loc1 = 0;
                char[] space2 = new char[len2];
                int loc2 = 0;

                // Walk through all following characters that are digits or
                // characters in BOTH strings starting at the appropriate marker.
                // Collect char arrays.
                do
                {
                    space1[loc1++] = ch1;
                    marker1++;

                    if (marker1 < len1)
                    {
                        ch1 = s1[marker1];
                    }
                    else
                    {
                        break;
                    }
                } while (char.IsDigit(ch1) == char.IsDigit(space1[0]));

                do
                {
                    space2[loc2++] = ch2;
                    marker2++;

                    if (marker2 < len2)
                    {
                        ch2 = s2[marker2];
                    }
                    else
                    {
                        break;
                    }
                } while (char.IsDigit(ch2) == char.IsDigit(space2[0]));

                // If we have collected numbers, compare them numerically.
                // Otherwise, if we have strings, compare them alphabetically.
                string str1 = new string(space1);
                string str2 = new string(space2);

                int result = 0;

                if (char.IsDigit(space1[0]) && char.IsDigit(space2[0]))
                {
                    try
                    {
                        int thisNumericChunk = int.Parse(str1);
                        int thatNumericChunk = int.Parse(str2);
                        result = thisNumericChunk.CompareTo(thatNumericChunk);    
                    }catch(Exception ex) 
                    {
                        if (ex is OverflowException)
                        {
                            result = str1.CompareTo(str2);
                        }
                    }
                }
                else
                {
                    result = str1.CompareTo(str2);
                }

                if (result != 0)
                {
                    return result;
                }
            }
            return len1 - len2;
        }

        public int Compare(decimal x, decimal y)
        {
            if (x > y)
                return 1;
            else if (x < y)
                return -1;
            else
                return 0;
        }

        public int Compare(DateTime date1, DateTime date2)
        {
            if (date1 > date2)
                return 1;
            else if (date1 < date2)
                return -1;
            else
                return 0;
        }

    }
}