我有一些奇怪的问题与ListView拒绝正确排序自己。我在程序中99%的ListView上都使用了这个代码它们工作得很好。然而,对于一个ListView(它曾经工作过),它拒绝工作挂起程序。当我在两种方法上都添加换行符时。它到达ListViewColumnSorter.columnClick(listViewKlienci, ref lvwColumnSorterKlienci, sender, e, headerIcons);
,然后通过代码到达varListView.Sort();
,然后停在这里。永远不会达到方法的终点。ListView
非常简单,只有2列和一些颜色。
private void listViewKlienci_ColumnClick(object sender, ColumnClickEventArgs e) {
ListViewColumnSorter.columnClick(listViewKlienci, ref lvwColumnSorterKlienci, sender, e, headerIcons);
ListViewHelper.listViewResize(listViewKlienci);
}
public static void columnClick(ListView varListView, ref ListViewColumnSorter lvwColumnSorter, object sender, ColumnClickEventArgs e, ImageList headerImages) {
//get list view header
IntPtr hHeader = SendMessage(varListView.Handle, LVM_GETHEADER, IntPtr.Zero, IntPtr.Zero);
SendMessage(hHeader, HDM_SETIMAGELIST, IntPtr.Zero, headerImages.Handle);
SortOrder Order = SortOrder.Descending;
//format icons
HDITEM hd = new HDITEM {
mask = HDI_IMAGE | HDI_FORMAT
};
for (int i = 0; i < varListView.Columns.Count; i++) {
// if (i != e.Column) {
hd.fmt = HDF_LEFT | HDF_STRING;
hd.iImage = -1;
SendMessage(hHeader, HDM_SETITEM, new IntPtr(i), ref hd);
// }
}
hd.fmt = HDF_LEFT | HDF_STRING | HDF_BITMAP_ON_RIGHT;
ListViewHelper.enableDoubleBuffer(varListView);
if (Order != SortOrder.None) {
hd.fmt |= HDF_IMAGE;
}
if (e.Column == lvwColumnSorter.SortColumn) {
if (lvwColumnSorter.Order == SortOrder.Ascending) {
hd.iImage = 0;
lvwColumnSorter.Order = SortOrder.Descending;
} else {
hd.iImage = 1;
lvwColumnSorter.Order = SortOrder.Ascending;
}
} else {
hd.iImage = 1;
lvwColumnSorter.SortColumn = e.Column;
lvwColumnSorter.Order = SortOrder.Ascending;
}
SendMessage(hHeader, HDM_SETITEM, new IntPtr(e.Column), ref hd);
varListView.Sort();
}
, Compare
在Sort()中被大量执行。
/// <summary>
/// This method is inherited from the IComparer interface. It compares the two objects passed using a case insensitive comparison.
/// </summary>
/// <param name = "x">First object to be compared</param>
/// <param name = "y">Second object to be compared</param>
/// <returns>The result of the comparison. "0" if equal, negative if 'x' is less than 'y' and positive if 'x' is greater than 'y'</returns>
public int Compare(object x, object y) {
int compareResult;
var listviewX = (ListViewItem) x;
var listviewY = (ListViewItem) y;
string s1 = listviewX.SubItems.Count > ColumnToSort ? listviewX.SubItems[ColumnToSort].Text : String.Empty;
string s2 = listviewY.SubItems.Count > ColumnToSort ? listviewY.SubItems[ColumnToSort].Text : String.Empty;
int i1;
int i2;
DateTime date1;
DateTime date2;
decimal d1;
decimal d2;
if (int.TryParse(s1, out i1) && int.TryParse(s2, out i2)) {
compareResult = ObjectCompare.Compare(i1, i2);
} else if (DateTime.TryParse(s1, out date1) && DateTime.TryParse(s2, out date2)) {
compareResult = ObjectCompare.Compare(date1, date2);
} else if (Locale.returnDecimalFromZl(s1, out d1) && Locale.returnDecimalFromZl(s2, out d2)) {
compareResult = ObjectCompare.Compare(d1, d2);
} else {
compareResult = ObjectCompare.Compare(s1, s2);
}
// Calculate correct return value based on object comparison
if (OrderOfSort == SortOrder.Ascending) {
// Ascending sort is selected, return normal result of compare operation
return compareResult;
} else if (OrderOfSort == SortOrder.Descending) {
// Descending sort is selected, return negative result of compare operation
return (-compareResult);
} else {
// Return '0' to indicate they are equal
return 0;
}
}
如果我改变代码一点,删除所有的If,只留下一个比较,它立即返回结果。
//if (int.TryParse(s1, out i1) && int.TryParse(s2, out i2)) {
// compareResult = ObjectCompare.Compare(i1, i2);
//} else if (DateTime.TryParse(s1, out date1) && DateTime.TryParse(s2, out date2)) {
// compareResult = ObjectCompare.Compare(date1, date2);
//} else if (Locale.returnDecimalFromZl(s1, out d1) && Locale.returnDecimalFromZl(s2, out d2)) {
// compareResult = ObjectCompare.Compare(d1, d2);
//} else {
compareResult = ObjectCompare.Compare(s1, s2);
// }
似乎这就是……的原因。但它在Visual Studio之外工作得很好,只是在Visual Studio中它会导致很大的减速。
我进一步开始添加更多的比较结果,只有最后一个导致放缓:
public static bool returnDecimalFromZl(string dataToCheck, out decimal value) {
if (dataToCheck.Trim() != "") { // && dataToCheck.Contains(" zł")) {
try {
value = Decimal.Parse(dataToCheck.Trim(), NumberStyles.Number | NumberStyles.AllowCurrencySymbol);
return true;
} catch {
value = 0m;
return false;
}
}
value = 0m;
return false;
}
如果我把它改成:
public static bool returnDecimalFromCurrency(string dataToCheck, out decimal value) {
if ((dataToCheck.Trim() != "") && (dataToCheck.Contains(" zł"))) {
try {
value = Decimal.Parse(dataToCheck.Trim(), NumberStyles.Number | NumberStyles.AllowCurrencySymbol);
return true;
} catch {
value = 0m;
return false;
}
}
value = 0m;
return false;
}
它立即开始工作。这在方法上只有&& (dataToCheck.Contains(" zł"))
。奇怪的东西!
EDIT1:有趣的是,在我让它运行5-10分钟后,它从Sort成功返回…
EDIT2。使用第一列排序可以工作。第二列保存人名(1200~人名)
EDIT3。排序以外的Visual Studio工作得很好(我去BIN目录在项目和执行我的应用程序排序在1秒)。所以似乎只有Visual Studio受到了影响。我甚至把我的旧硬盘放在我的电脑上,安装了不同(相同版本)的Visual Studio,问题仍然存在。
标引。如果我启动PROFILER,如RedGate ANTS PROFILER从Visual Studio问题不显示和ListView排序是非常快…$#^$*$#%
您了解了为什么在。net 2.0版本中添加了TryParse()方法。切换到Output窗口,观察数千条"第一次机会"异常通知消息。当附加了调试器时,异常处理变得非常昂贵。
发现当我从
public static bool returnDecimalFromZl(string dataToCheck, out decimal value) {
if (dataToCheck.Trim() != "") {
try {
value = Decimal.Parse(dataToCheck.Trim(), NumberStyles.Number | NumberStyles.AllowCurrencySymbol);
return true;
} catch {
value = 0m;
return false;
}
}
value = 0m;
return false;
}
如果我把它改成:
public static bool returnDecimalFromZl(string dataToCheck, out decimal value) {
if ((dataToCheck.Trim() != "") && (dataToCheck.Contains(" zł"))) {
try {
value = Decimal.Parse(dataToCheck.Trim(), NumberStyles.Number | NumberStyles.AllowCurrencySymbol);
return true;
} catch {
value = 0m;
return false;
}
}
value = 0m;
return false;
}
程序也开始在Visual Studio中正常工作了。为什么它在Visual Studio外部和内部使用时表现正常,我不知道。1200个对象的速度差异为5-10分钟:/