Answered by:
How to sort Form.Controls collection base on my criteria ?

Question
-
Answers
-
i think this code works fine, but sorting base on 'X' location must be Desc (not asc). how can i change this code to accomplish this ?
Hamed, Rudy's reply need a little modification; you hardly mark as answer a reply ;)public class PointComparer : IComparer<Control> { #region IComparer<Control> Members public int Compare(Control x, Control y) { Int64 xp = ((Int64)x.Location.Y << 32) + (Int32.MaxValue - x.Location.X); Int64 yp = ((Int64)y.Location.Y << 32) + (Int32.MaxValue - y.Location.X); return xp.CompareTo(yp); } #endregion }
LEARN HOW TO USE WINDOWS API DURING A QUICK, SIMPLE AND PRACTICAL HOW TO:
How To: Changing TextBox blinking caret using Windows API -
decimal GenerateComparer(Point location)
{
decimal yloc = (decimal)location.Y;
decimal xloc = (decimal)location.X;
return yloc + ((1000m - xloc) / 1000m); // modification here
}
Mark the best replies as answers. "Fooling computers since 1971."- Proposed as answer by Yasser Zamani - Mr. Help Sunday, February 20, 2011 4:18 AM
- Marked as answer by Neddy Ren Wednesday, February 23, 2011 3:28 AM
All replies
-
A sample implementation would be as shown below:
foreach (Control c in this.Controls) { int yAxis = c.Location.Y; int xAxis = c.Location.X; // Store this values somewhere and sort it accordingly }
Balaji Baskar
http://codesupport.wordpress.com
Click on "Vote As Helpful" and "Mark As Answer" if this has helped you. -
A sample implementation would be as shown below:
foreach (Control c in this.Controls) { int yAxis = c.Location.Y; int xAxis = c.Location.X; // Store this values somewhere and sort it accordingly }
Balaji Baskar
http://codesupport.wordpress.com
Click on "Vote As Helpful" and "Mark As Answer" if this has helped you.Thanks
but i want to sort my controls collection base on my criterias.
http://www.codeproject.com/KB/codegen/DatabaseHelper.aspx -
how about something like this? note here that i am storing data in datatable and querying it.
DataTable dtControls = new DataTable(); dtControls.Columns.Add("ControlName",typeof(string)); dtControls.Columns.Add("X",typeof(int)); dtControls.Columns.Add("Y",typeof(int)); foreach (Control c in this.Controls) { dtControls.Rows.Add(c.Name, c.Location.X, c.Location.Y); } // Sorts controls in Y axis ascending DataRow[] xSort = dtControls.Select(null, "Y ASC"); // Sorts controls in X axis descending DataRow[] ySort = dtControls.Select(null, "X DESC");
Balaji Baskar
http://codesupport.wordpress.com
Click on "Vote As Helpful" and "Mark As Answer" if this has helped you. -
how about something like this? note here that i am storing data in datatable and querying it.
DataTable dtControls = new DataTable(); dtControls.Columns.Add("ControlName",typeof(string)); dtControls.Columns.Add("X",typeof(int)); dtControls.Columns.Add("Y",typeof(int)); foreach (Control c in this.Controls) { dtControls.Rows.Add(c.Name, c.Location.X, c.Location.Y); } // Sorts controls in Y axis ascending DataRow[] xSort = dtControls.Select(null, "Y ASC"); // Sorts controls in X axis descending DataRow[] ySort = dtControls.Select(null, "X DESC");
Balaji Baskar
http://codesupport.wordpress.com
Click on "Vote As Helpful" and "Mark As Answer" if this has helped you.Thanks Balaji
your post was helpful for me. many thanks.
any way, i found a way to accomplish this via List<T>.Sort method as follow :
List<Control> controls = new List<Control>(); foreach (Control c in this.Controls) controls.Add(c); controls.Sort(delegate(Control c1, Control c2) { return Comparer<int>.Default.Compare(c1.Location.Y, c2.Location.Y); }); controls.Sort(delegate(Control c1, Control c2) { return Comparer<int>.Default.Compare(c2.Location.X, c1.Location.X); });
but does not give me a correct result as i expected!
can u test this code ?
thanks in advance
http://www.codeproject.com/KB/codegen/DatabaseHelper.aspx -
Create a custom collection class---inherited from List<t>---that sorts items as they are added.
It might prove to be useful to create a custom item class that wraps Control.
http://msdn.microsoft.com/en-us/library/234b841s.aspx
Mark the best replies as answers. "Fooling computers since 1971."
-
Create a custom collection class---inherited from List<t>---that sorts items as they are added.
It might prove to be useful to create a custom item class that wraps Control.
Mark the best replies as answers. "Fooling computers since 1971."
Hi
Can u give me an example which how to accomplish this ?
thanks
http://www.codeproject.com/KB/codegen/DatabaseHelper.aspx -
I did.
You deleted the link when you quoted my reply. The IComparer interface specifies a method that compares just 2 items. The rest is taken care of by the internals of the List<>Sort method overload that specifies an IComparer instance to be used to perform the Sort.
Mark the best replies as answers. "Fooling computers since 1971." -
I did.
You deleted the link when you quoted my reply. The IComparer interface specifies a method that compares just 2 items. The rest is taken care of by the internals of the List<>Sort method overload that specifies an IComparer instance to be used to perform the Sort.
Mark the best replies as answers. "Fooling computers since 1971."Sorry
but i did not got your mean!
can u give me an example or more description ?
thanks
http://www.codeproject.com/KB/codegen/DatabaseHelper.aspx -
http://msdn.microsoft.com/en-us/library/234b841s.aspx
Mark the best replies as answers. "Fooling computers since 1971." -
-
Dude. I already told you that all the method needs to do is compare just 2 items. That means compare just two controls according to any criteria you define.
Yes, the example compares two strings. You need to create a method that compares only 2 controls. Compare the Y values, and then compare the X values if the Y values are the same. Done. You do not need anything as fancy as what you posted earlier.
Here's the non-generic overload of List.Sort. It is identical, just not as complicated looking.
http://msdn.microsoft.com/en-us/library/0e743hdt.aspx
All the method needs to do is return a positive number or a negative number depending upon which of the 2 input parameters is "greater". Return a zero if they are "equal".
Mark the best replies as answers. "Fooling computers since 1971." -
create a class to store your data:
public class CustomControls { private string controlName; public string ControlName { get { return controlName; } set { controlName = value; } } private int xAxis; public int XAxis { get { return xAxis; } set { xAxis = value; } } private int yAxis; public int YAxis { get { return yAxis; } set { yAxis = value; } } }
and the in the form code the implementation logic can be this way:
List<CustomControls> customCtrls = new List<CustomControls>(); foreach (Control c in this.Controls) { CustomControls ctrl = new CustomControls(); ctrl.ControlName = c.Name; ctrl.XAxis = c.Location.X; ctrl.YAxis = c.Location.Y; customCtrls.Add(ctrl); } // Sorting in Ascending (Y Axis) customCtrls.Sort(delegate(CustomControls c1, CustomControls c2) { return c1.YAxis.CompareTo(c2.YAxis); }); // Sorting in Descending (X Axis) customCtrls.Sort(delegate(CustomControls c1, CustomControls c2) { return c1.XAxis.CompareTo(c2.XAxis); }); customCtrls.Reverse();
Balaji Baskar
http://codesupport.wordpress.com
Click on "Vote As Helpful" and "Mark As Answer" if this has helped you. -
This custom Comparer class compares just the Location.Y values. You would use this with the method at the link in my previous post.
class MyControls : List<Control>
{
ControlLocationComparer comparer = new ControlLocationComparer();
public new void Add(Control item)
{
this.Add(item);
this.Sort(this.comparer);
}
class ControlLocationComparer : IComparer<Control>
{
#region IComparer<Control> Members
public int Compare(Control x, Control y)
{
int result = 0;
Control ctrl_x = x as Control;
Control ctrl_y = y as Control;
if ( ctrl_x == null || ctrl_y == null )
{
throw new NullReferenceException("Compared item was null.");
}
if ( ctrl_x.Location.Y > ctrl_y.Location.Y )
{
result = 1;
}
if ( ctrl_x.Location.Y < ctrl_y.Location.Y )
{
result = -1;
}
return result;
}
#endregion
}
}
Mark the best replies as answers. "Fooling computers since 1971." -
create a class to store your data:
public class CustomControls { private string controlName; public string ControlName { get { return controlName; } set { controlName = value; } } private int xAxis; public int XAxis { get { return xAxis; } set { xAxis = value; } } private int yAxis; public int YAxis { get { return yAxis; } set { yAxis = value; } } }
and the in the form code the implementation logic can be this way:
List<CustomControls> customCtrls = new List<CustomControls>(); foreach (Control c in this.Controls) { CustomControls ctrl = new CustomControls(); ctrl.ControlName = c.Name; ctrl.XAxis = c.Location.X; ctrl.YAxis = c.Location.Y; customCtrls.Add(ctrl); } // Sorting in Ascending (Y Axis) customCtrls.Sort(delegate(CustomControls c1, CustomControls c2) { return c1.YAxis.CompareTo(c2.YAxis); }); // Sorting in Descending (X Axis) customCtrls.Sort(delegate(CustomControls c1, CustomControls c2) { return c1.XAxis.CompareTo(c2.XAxis); }); customCtrls.Reverse();
Balaji Baskar
http://codesupport.wordpress.com
Click on "Vote As Helpful" and "Mark As Answer" if this has helped you.Thanks Balaji
but this code does not return my expected result.
http://www.codeproject.com/KB/codegen/DatabaseHelper.aspx -
Hamed,
We don't understand what "your expected result" actually is. You are looking for a concise solution by provided only vague descriptions of whatever it is that you are after. You have declared the previous suggestion as wrong. Yet, you fail to describe exactly "what" is wrong, and what "right" should actually be.
No one understands your objective, Hamed. Telling people over and over, "That's not my expected result," is almost laughable. You paint a picture of yourself that says you want others to do your work while you stand back and watch. It is almost laughbable, but truthfully it is pretty sad. You actually posted code and asked someone to test it for you. Now that was funny.
I posted code that will only sort by the Location.Y value for a reason. I don't know how the Location.X values should be sorted. Too many unkowns to even try. So, I posted code to meet you halfway. Though my code snippet only sorts the "Y" values, it could very easily be extended to sort the "X" values. Try it. Does it sort the "Y" values?
Rudy =8^D
Mark the best replies as answers. "Fooling computers since 1971."- Edited by Rudedog2 Saturday, February 19, 2011 3:38 PM
-
I wrote a new class to use as a Comparer object in my previous post.
public decimal MaximumX;
public decimal MaximumY;
class PointComparer : IComparer<Control>
{
#region IComparer<Control> Members
public int Compare(Control x, Control y)
{
decimal xp = GenerateComparer(x.Location);
decimal yp = GenerateComparer(y.Location);
return Decimal.Compare(xp, yp);
}
decimal GenerateComparer(Point location)
{
decimal yloc = (decimal)location.Y;
decimal xloc = (decimal)location.X;
return yloc + (xloc / 1000m);
}
#endregion
}
The variables declared in the GenerateComparer method might need some adjusting to compensate ascending or descending sorting.
Mark the best replies as answers. "Fooling computers since 1971." -
Hamed,
We don't understand what "your expected result" actually is. You are looking for a concise solution by provided only vague descriptions of whatever it is that you are after. You have declared the previous suggestion as wrong. Yet, you fail to describe exactly "what" is wrong, and what "right" should actually be.
No one understands your objective, Hamed. Telling people over and over, "That's not my expected result," is almost laughable. You paint a picture of yourself that says you want others to do your work while you stand back and watch. It is almost laughbable, but truthfully it is pretty sad.
I posted code that will only sort by the Location.Y value for a reason. I don't know how the Location.X values should be sorted. Too many unkowns to even try. So, I posted code to meet you halfway. Though my code snippet only sorts the "Y" values, it could very easily be extended to sort the "X" values. Try it. Does it sort the "Y" values?
Rudy =8^D
Mark the best replies as answers. "Fooling computers since 1971."Hi Rudy
sorry for my less description.
to understand what i need, please see this form image.
As you can see, there is a lot of controls on form in various places. i want to sort these controls first by 'Y Asc', then by 'X Desc'. my expected result would be this :
button2
txtY
txtX
button1
txtHeight
txtWidth
label1
textBox1
label2
textBox2
listBox1
label3
textBox3
thanks
http://www.codeproject.com/KB/codegen/DatabaseHelper.aspx -
I guess that means you have not tested my code, not even for your own self benefit.
Mark the best replies as answers. "Fooling computers since 1971." -
I created a custom collection class---inherited from List<Control>---that sorts the entire collection as new items are added.
Mark the best replies as answers. "Fooling computers since 1971." -
I created a custom collection class---inherited from List<Control>---that sorts the entire collection as new items are added.
Mark the best replies as answers. "Fooling computers since 1971."Thanks Rudy
i've tested your code. i've wrote this :
public class PointComparer : IComparer<Control> { #region IComparer<Control> Members public int Compare(Control x, Control y) { decimal xp = GenerateComparer(x.Location); decimal yp = GenerateComparer(y.Location); return Decimal.Compare(xp, yp); } decimal GenerateComparer(Point location) { decimal yloc = (decimal)location.Y; decimal xloc = (decimal)location.X; return yloc + (xloc / 1000m); } #endregion } List<Control> controls = new List<Control>(); foreach (Control c in this.Controls) controls.Add(c); PointComparer comparer = new PointComparer(); controls.Sort(comparer); foreach (Control c in controls) { listBox1.Items.Add(string.Format("{0}- {1}:{2}", c.Name, c.Location.X, c.Location.Y)); }
i think this code works fine, but sorting base on 'X' location must be Desc (not asc). how can i change this code to accomplish this ?
thanks
http://www.codeproject.com/KB/codegen/DatabaseHelper.aspx -
i think this code works fine, but sorting base on 'X' location must be Desc (not asc). how can i change this code to accomplish this ?
Hamed, Rudy's reply need a little modification; you hardly mark as answer a reply ;)public class PointComparer : IComparer<Control> { #region IComparer<Control> Members public int Compare(Control x, Control y) { Int64 xp = ((Int64)x.Location.Y << 32) + (Int32.MaxValue - x.Location.X); Int64 yp = ((Int64)y.Location.Y << 32) + (Int32.MaxValue - y.Location.X); return xp.CompareTo(yp); } #endregion }
LEARN HOW TO USE WINDOWS API DURING A QUICK, SIMPLE AND PRACTICAL HOW TO:
How To: Changing TextBox blinking caret using Windows API -
decimal GenerateComparer(Point location)
{
decimal yloc = (decimal)location.Y;
decimal xloc = (decimal)location.X;
return yloc + ((1000m - xloc) / 1000m); // modification here
}
Mark the best replies as answers. "Fooling computers since 1971."- Proposed as answer by Yasser Zamani - Mr. Help Sunday, February 20, 2011 4:18 AM
- Marked as answer by Neddy Ren Wednesday, February 23, 2011 3:28 AM
-
Thanks, Yasser.
Hamed,
Yasser's solution does the same thing using Integers, that mine does with decimals. I figured the decimal example might be easier to understand, but Yasser's solution should be faster.
I still suggest that you use the custom collection class. It will guarantee that the collection is always sorted.
Mark the best replies as answers. "Fooling computers since 1971."