Sort Gridview columns in C#

Hello Experts,
I am trying to sort few columns in a Gridview.  All the Alpha columns working as expected.  But, I have a numeric column (Serial Number) not working as expected.  Please see below and let me know how to fix it.

Thank you very much in advance.

Serial Number (when page loaded)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

Serial Number (when sorted)
1
10
11
12
13
14
15
2
3
4
5
6
7
8
9
RadhaKrishnaKiJayaAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Pawan KumarDatabase ExpertCommented:
Looks like you are sorting using text data. You need to use the Integer sorting. Can I see the code you using.?
0
RadhaKrishnaKiJayaAuthor Commented:
Thank you Pawan for your response.  I am trying to generate Serial Number (intSN ) in the loop and populate the Grid View.  Here I am converting it to string before it is displayed.  But it fails during Sorting.

    if (objSqlReader.HasRows == true)
    {
      RecordFound = true;
      string strCustInfo = string.Empty;
      string[] arrCustInfo = null;
      int intSN = 0;

      while (objSqlReader.Read())
      {
          strCustInfo = objSqlReader.GetValue(objSqlReader.GetOrdinal("CUSTOMER")).ToString().Trim();
          if (strCustInfo.IndexOf('|') != -1)
          {
            intSN += 1;
            objOptNode1.Attributes["SN"].InnerText = intSN.ToString();
            objOptNode1.Attributes["LASTNAME"].InnerText = arrCustInfo[0].Trim();
            objOptNode1.Attributes["FIRSTNAME"].InnerText = arrCustInfo[1].Trim();
            .
            .
            .
          }
          objFailureReasonOutXml.DocumentElement.AppendChild(objOptNode1);
          objOptNode1 = objOptNode.CloneNode(true);
      }
    }
0
it_saigeDeveloperCommented:
You need to implement a natural sort comparer.  From a previous EE PAQ - https:/Q_28586081.html#a40515582
	public class NaturalComparer : Comparer<string>, IDisposable
	{
		private Dictionary<string, string[]> table;

		public NaturalComparer()
		{
			table = new Dictionary<string, string[]>();
		}

		public void Dispose()
		{
			table.Clear();
			table = null;
		}

		public override int Compare(string x, string y)
		{
			if (x == y)
			{
				return 0;
			}
			string[] x1, y1;
			if (!table.TryGetValue(x, out x1))
			{
				x1 = Regex.Split(x.Replace(" ", ""), "([0-9]+)");
				table.Add(x, x1);
			}
			if (!table.TryGetValue(y, out y1))
			{
				y1 = Regex.Split(y.Replace(" ", ""), "([0-9]+)");
				table.Add(y, y1);
			}

			for (int i = 0; i < x1.Length && i < y1.Length; i++)
			{
				if (x1[i] != y1[i])
					return PartCompare(x1[i], y1[i]);
			}

			if (y1.Length > x1.Length)
				return 1;
			else if (x1.Length > y1.Length)
				return -1;
			else
				return 0;
		}

		private static int PartCompare(string left, string right)
		{
			int x, y;
			if (!int.TryParse(left, out x))
				return left.CompareTo(right);

			if (!int.TryParse(right, out y))
				return left.CompareTo(right);

			return x.CompareTo(y);
		}
	}

Open in new window


Usage -
	class Program
	{
		private static List<UserPrincipal> users = new List<UserPrincipal>();

		static void Main(string[] args)
		{
			PrincipalContext context = new PrincipalContext(ContextType.Domain);
			UserPrincipal user = new UserPrincipal(context);
			PrincipalSearcher searcher = new PrincipalSearcher(user);
			foreach (Principal result in searcher.FindAll())
			{
				UserPrincipal upe = result as UserPrincipal;
				if (upe != null)
					users.Add(upe);
			}

			using (NaturalComparer comparer = new NaturalComparer())
				users.Sort((a, b) => comparer.Compare(a.SamAccountName, b.SamAccountName));

			foreach (UserPrincipal up in users)
				Console.WriteLine("User: {0}; SamAccount: {1}", up.Name, up.SamAccountName);

			Console.ReadLine();
		}
	}

Open in new window


-saige-
0
Cloud Class® Course: Microsoft Exchange Server

The MCTS: Microsoft Exchange Server 2010 certification validates your skills in supporting the maintenance and administration of the Exchange servers in an enterprise environment. Learn everything you need to know with this course.

RadhaKrishnaKiJayaAuthor Commented:
Hello it_saige,
Please look at my code and apply a fix.  That would be very helpful.

Thank you!
0
Fernando SotoRetiredCommented:
Hi RadhaKrishnaKiJaya;

To your statement, "But, I have a numeric column (Serial Number) not working as expected.", It is because the characters being sorted are text character and are representing numeric data which they are not. As you stated, "I am trying to generate Serial Number (intSN ) in the loop and populate the Grid View.  Here I am converting it to string before it is displayed.  But it fails during Sorting.". If you need to convert to a string you should pad the beginning of the string with leading zeros as many as the largest serial number that can be created or to not convert to text characters and just use as integer values.
0
RadhaKrishnaKiJayaAuthor Commented:
Fernando Soto,
Thank you for your reply.  I tried to populate the column without converting it to string (see code below).  But got the error "cannot implicitly convert type int to string" during coding.  If I use leading zeros, I don't want to display them in the column as I just want to display 1, not 001.  Please let me know if there is a way to hide it.  Thank you again!

objOptNode1.Attributes["SN"].InnerText = intSN;
0
Fernando SotoRetiredCommented:
Hi RadhaKrishnaKiJaya

In order to help with this question I need to know what the data type of objOptNode1 is so please post the class definition as well as how you load the DataGrid.
Are you loading a XML document and loading the DataGrid with it?
0
RadhaKrishnaKiJayaAuthor Commented:
Fernando Soto,
Yes, we are loading the XML document to the DataGrid directly.  Please see below code.  

Thank you!


XmlDocument objFailureReasonOutXml = new XmlDocument();
XmlNode objOptNode1;

.
if (objSqlReader.HasRows == true)
    {
      RecordFound = true;
      string strCustInfo = string.Empty;
      string[] arrCustInfo = null;
      int intSN = 0;

      while (objSqlReader.Read())
      {
          strCustInfo = objSqlReader.GetValue(objSqlReader.GetOrdinal("CUSTOMER")).ToString().Trim();
          if (strCustInfo.IndexOf('|') != -1)
          {
            intSN += 1;
            objOptNode1.Attributes["SN"].InnerText = intSN.ToString();
            objOptNode1.Attributes["LASTNAME"].InnerText = arrCustInfo[0].Trim();
            objOptNode1.Attributes["FIRSTNAME"].InnerText = arrCustInfo[1].Trim();
            .
            .
            .
          }
          objFailureReasonOutXml.DocumentElement.AppendChild(objOptNode1);
          objOptNode1 = objOptNode.CloneNode(true);
      }
    }
.

objFailureReasonOutXml.DocumentElement.AppendChild(objOptNode1);
0
Pawan KumarDatabase ExpertCommented:
Go to the page load
add

yourGridviewId.SortCompare += YourSorting; 

Open in new window


Add the below function-

private void YourSorting(object sender, DataGridViewSortCompareEventArgs e)
{
    int FirstCellValue = int.Parse(e.CellValue1.ToString())
	, SecondCellValue = int.Parse(e.CellValue2.ToString());
    e.SortResult = FirstCellValue.CompareTo(SecondCellValue);
    e.Handled = true;
}

Open in new window

0
RadhaKrishnaKiJayaAuthor Commented:
Hello Pawan Kumar,
This is a Web project.  DataGridViewSortCompareEventArgs can be used in Windows Forms.  Please let me know if I am missing anything.

Thank you!
0
Fernando SotoRetiredCommented:
Hi RadhaKrishnaKiJaya

The XML attribute is a text value and so when directly assigned to a DataGrid it does not convert it to numeric data. I am not a web developer so I need to see how you create the DataGrid and how you initialize it and how you assign the XML to the DataGrid so I can see if there is a way to do what you need.
0
RadhaKrishnaKiJayaAuthor Commented:
I added the leading zeros manually during reading the lines as below.  I did not find any better solution.

objOptNode1.Attributes["SN"].InnerText = intSN.ToString("000");

Thank you all.
0
Fernando SotoRetiredCommented:
Hi RadhaKrishnaKiJaya;

As I stated in my post #42358684 to do what you ended up doing but you did not assign the points to my solution.
0
Fernando SotoRetiredCommented:
Hi thermoduric;

I stated in my post 42358684 that to sort text that represented numeric data that he needed to pad the text with leading zero characters so that they will sort correctly. RadhaKrishnaKiJaya in the following post 42358817 that he did not want to do that because he did not want them to be displayed with leading zeros. Then RadhaKrishnaKiJaya  on post 42380000 went with the suggestion to use leading zeros. Seeming that RadhaKrishnaKiJaya used my suggestion I would think that it should have been selected as the Best Solution.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
RadhaKrishnaKiJayaAuthor Commented:
Hello Fernando,
I totally forgot about your post.  Yes, you are 100% right.  I missed that.

Thank you again!
0
Fernando SotoRetiredCommented:
Not a problem RadhaKrishnaKiJaya, all is good.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
ASP.NET

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.