当列为字符串时动态排序 ObservableCollection<object>
Dynamically sorting an ObservableCollection<object> when the column is a string
我有一个 Observable 集合,其中包含从 SQL 查询返回到我的 WCF 服务的大约 5,000 个对象。我被要求按对象中的 3 个字段对集合进行排序。为简洁起见,假设这是我的 C# 模型:
public class TestObject{
public string type1{get; set;}
public string type2{get; set;}
public string type3(get; set;}
}
这是我必须尝试排序的一些测试数据:
public ObservableCollection<TestObject> TestObjects = new ObservableCollection<TestObject>();
TestObjects.Add(new TestObject('708','4','(A)'));
TestObjects.Add(new TestObject('7','41B','1(A)'));
TestObjects.Add(new TestObject('69','2','45'));
TestObjects.Add(new TestObject('708','4','(B)'));
TestObjects.Add(new TestObject('69','2','5'));
TestObjects.Add(new TestObject('7','41','1(B)'));
TestObjects.Add(new TestObject('7','41',''));
有没有办法对这些进行动态排序,以便 Observable 集合返回时像这样排序?
{(7,41,''),(7,41,1(B)),(7,41B,1(A)),(69,2,5),(69,2,45),(708,4,(A)),(708,4,(B))}
到目前为止,我已经能够按 type1 对它们进行排序,但随后尝试按 type2 进行排序时,将 type1 排序的顺序搞砸了。这是我用来尝试排序的方法,然后是我如何称呼它:
protected virtual ObservableCollection<TestObject> SortTestObjects(ObservableCollection<TestObjects> unsortedObjects, string level){
var SortedObjects = new ObservableCollection<TestObject>();
Comparison<TestObject> numericComp;
Comparison<TestObject> comparison;
Comparison<TestObject> AlphaNumericComp;
bool sortNumeric = false;
switch (level)
{
case "type1":
numericComp = (a, b) =>
{
var aKey = Convert.ToDouble(a.type1);
var bKey = Convert.ToDouble(b.type1);
return aKey.CompareTo(bKey);
};
AlphaNumericComp = (a, b) =>
{
return string.CompareOrdinal(a.type1, b.type1);
};
sortNumeric = unsortedObjects.ToList().TrueForAll(i => i.type1.IsNumeric());
break;
case "type2":
numericComp = (a, b) =>
{
var aKey = Convert.ToDouble(a.type2);
var bKey = Convert.ToDouble(b.type2);
return aKey.CompareTo(bKey);
};
AlphaNumericComp = (a, b) =>
{
return string.CompareOrdinal(a.type2, b.type2);
};
sortNumeric = unsortedObjects.ToList().TrueForAll(i => i.type2.IsNumeric());
break;
case "type3":
numericComp = (a, b) =>
{
var aKey = Convert.ToDouble(a.type3);
var bKey = Convert.ToDouble(b.type3);
return aKey.CompareTo(bKey);
};
AlphaNumericComp = (a, b) =>
{
return string.CompareOrdinal(a.type3, b.type3);
};
sortNumeric = unsortedObjects.ToList().TrueForAll(i => i.type3.IsNumeric());
break;
default:
numericComp = (a, b) =>
{
var aKey = Convert.ToDouble(a.type1);
var bKey = Convert.ToDouble(b.type1);
return aKey.CompareTo(bKey);
};
AlphaNumericComp = (a, b) =>
{
return string.CompareOrdinal(a.type1, b.type1);
};
sortNumeric = unsortedObjects.ToList().TrueForAll(i => i.type1.IsNumeric());
break;
}
comparison = sortNumeric ? numericComp : AlphaNumericComp;
unsortedObjects.ToList().Sort(comparison);
foreach(var obj in unsortedOjects){
SortedObjects.Add(obj)
}
return SortedObjects;
}
Public ObservableCollection<TestObject> SortAllTestObjects(){
var sort1 = SortTestObjects(TestObjects, "type1");
var sort2 = SortTestObjects(sort1, "type2");
var sort3 = SortTestObjects(sort2, "type3");
return sort3;
}
**编辑:这是我将在此示例中使用的 SQL 查询。只要我在客户端中得到正确的顺序,我就完全可以更改查询 **
Select type1, type2, type3 from dbo.testObject tO where tO.del_date is null
如果您需要更多信息,请告诉我。任何帮助或建设性的反馈都会很棒!
您可以使用 OrderBy() 和 ThenBy()。
例子
public class SomeClass
{
public string PropA { get; }
public string PropB { get; }
}
protected ObservableCollection<SomeClass> SomeFunc(ObservableCollection<SomeClass> collection)
{
var sorted=collection.OrderBy(s => s.PropA).ThenBy(s => s.PropB);
ObservableCollection<SomeClass> sortedObservable=new ObservableCollection<SomeClass>();
foreach(var item in sorted)
{
sortedObservable.Add(item);
}
return sortedObservable;
}
要考虑字符串中的数值,您可以使用自定义比较器,The answer to this is a good example
这就是我最终解决问题的方法。在对象中,我连接了类型
public class TestObject{
public string type1{get; set;}
public string type2{get; set;}
public string type3{get; set;}
public string types{get;set;}
}
在填充 TestObjects 的方法中,我将其添加到:
public ObservableCollection<TestObject> TestObjects = new ObservableCollection<TestObject>();
TestObjects.Add(new TestObject('708','4','(A)','708.4.(A)'));
TestObjects.Add(new TestObject('7','41B','1(A)','7.41B.1(A)'));
TestObjects.Add(new TestObject('69','2','45', '69.2.45'));
TestObjects.Add(new TestObject('708','4','(B)', '708.4.(B)'));
TestObjects.Add(new TestObject('69','2','5', '69.2.5'));
TestObjects.Add(new TestObject('7','41','1(B)', '7.41.1(B)'));
TestObjects.Add(new TestObject('7','41','', '7.41.'));
TestObjects= SortObjects(TestObjects);
接下来,我在 ViewModel 中创建了一个自定义比较方法,使用 "Shlwapi.dll':
[DllImport("Shlwapi.dll", Charset = Charset.Unicode)]
private static extern int StrCmpLogicalW(string x, string y);
public ObservableCollection<TestObject> SortObjects(ObservableCollection<TestObject> unsortedObjects){
var sortedCollection = new ObservableCollection<TestObject>();
var objectList = new List<TestObject>();
foreach(var obj in unsortedObjects){
objectList.Add(obj);
}
Comparison<TestObject> typesComp = (a,b) =>{
var aKey = a.types;
var bKey = b.types;
return StrCmpLogicalW(aKey,bKey);
}
objectList.Sort(typesComp);
foreach(var obj in objectList){
sortedCollection.Add(obj);
}
return sortedCollection;
}
此方法允许我按升序 return TestObjects 集合。仍在研究降序开关,当我得到它时会更新它。
更新:这是具有反转能力的 SortObjects 方法
public ObservableCollection<TestObject> SortObjects(ObservableCollection<TestObject> unsortedObjects, bool IsAscend){
var sortedCollection = new ObservableCollection<TestObject>();
var objectList = new List<TestObject>();
foreach(var obj in unsortedObjects){
objectList.Add(obj);
}
Comparison<TestObject> typesComp = (a,b) =>{
var aKey = a.types;
var bKey = b.types;
return StrCmpLogicalW(aKey,bKey);
}
objectList.Sort(typesComp);
if(!isAscend){
objectsList.Reverse();
}
foreach(var obj in objectList){
sortedCollection.Add(obj);
}
return sortedCollection;
}
然后调用这样的真/假参数进行升序:
TestObjects = SortObjects(TestObjects, true);
降序排列如下:
TestObjects = SortObjects(TestObjects, false);
我有一个 Observable 集合,其中包含从 SQL 查询返回到我的 WCF 服务的大约 5,000 个对象。我被要求按对象中的 3 个字段对集合进行排序。为简洁起见,假设这是我的 C# 模型:
public class TestObject{
public string type1{get; set;}
public string type2{get; set;}
public string type3(get; set;}
}
这是我必须尝试排序的一些测试数据:
public ObservableCollection<TestObject> TestObjects = new ObservableCollection<TestObject>();
TestObjects.Add(new TestObject('708','4','(A)'));
TestObjects.Add(new TestObject('7','41B','1(A)'));
TestObjects.Add(new TestObject('69','2','45'));
TestObjects.Add(new TestObject('708','4','(B)'));
TestObjects.Add(new TestObject('69','2','5'));
TestObjects.Add(new TestObject('7','41','1(B)'));
TestObjects.Add(new TestObject('7','41',''));
有没有办法对这些进行动态排序,以便 Observable 集合返回时像这样排序?
{(7,41,''),(7,41,1(B)),(7,41B,1(A)),(69,2,5),(69,2,45),(708,4,(A)),(708,4,(B))}
到目前为止,我已经能够按 type1 对它们进行排序,但随后尝试按 type2 进行排序时,将 type1 排序的顺序搞砸了。这是我用来尝试排序的方法,然后是我如何称呼它:
protected virtual ObservableCollection<TestObject> SortTestObjects(ObservableCollection<TestObjects> unsortedObjects, string level){
var SortedObjects = new ObservableCollection<TestObject>();
Comparison<TestObject> numericComp;
Comparison<TestObject> comparison;
Comparison<TestObject> AlphaNumericComp;
bool sortNumeric = false;
switch (level)
{
case "type1":
numericComp = (a, b) =>
{
var aKey = Convert.ToDouble(a.type1);
var bKey = Convert.ToDouble(b.type1);
return aKey.CompareTo(bKey);
};
AlphaNumericComp = (a, b) =>
{
return string.CompareOrdinal(a.type1, b.type1);
};
sortNumeric = unsortedObjects.ToList().TrueForAll(i => i.type1.IsNumeric());
break;
case "type2":
numericComp = (a, b) =>
{
var aKey = Convert.ToDouble(a.type2);
var bKey = Convert.ToDouble(b.type2);
return aKey.CompareTo(bKey);
};
AlphaNumericComp = (a, b) =>
{
return string.CompareOrdinal(a.type2, b.type2);
};
sortNumeric = unsortedObjects.ToList().TrueForAll(i => i.type2.IsNumeric());
break;
case "type3":
numericComp = (a, b) =>
{
var aKey = Convert.ToDouble(a.type3);
var bKey = Convert.ToDouble(b.type3);
return aKey.CompareTo(bKey);
};
AlphaNumericComp = (a, b) =>
{
return string.CompareOrdinal(a.type3, b.type3);
};
sortNumeric = unsortedObjects.ToList().TrueForAll(i => i.type3.IsNumeric());
break;
default:
numericComp = (a, b) =>
{
var aKey = Convert.ToDouble(a.type1);
var bKey = Convert.ToDouble(b.type1);
return aKey.CompareTo(bKey);
};
AlphaNumericComp = (a, b) =>
{
return string.CompareOrdinal(a.type1, b.type1);
};
sortNumeric = unsortedObjects.ToList().TrueForAll(i => i.type1.IsNumeric());
break;
}
comparison = sortNumeric ? numericComp : AlphaNumericComp;
unsortedObjects.ToList().Sort(comparison);
foreach(var obj in unsortedOjects){
SortedObjects.Add(obj)
}
return SortedObjects;
}
Public ObservableCollection<TestObject> SortAllTestObjects(){
var sort1 = SortTestObjects(TestObjects, "type1");
var sort2 = SortTestObjects(sort1, "type2");
var sort3 = SortTestObjects(sort2, "type3");
return sort3;
}
**编辑:这是我将在此示例中使用的 SQL 查询。只要我在客户端中得到正确的顺序,我就完全可以更改查询 **
Select type1, type2, type3 from dbo.testObject tO where tO.del_date is null
如果您需要更多信息,请告诉我。任何帮助或建设性的反馈都会很棒!
您可以使用 OrderBy() 和 ThenBy()。
例子
public class SomeClass
{
public string PropA { get; }
public string PropB { get; }
}
protected ObservableCollection<SomeClass> SomeFunc(ObservableCollection<SomeClass> collection)
{
var sorted=collection.OrderBy(s => s.PropA).ThenBy(s => s.PropB);
ObservableCollection<SomeClass> sortedObservable=new ObservableCollection<SomeClass>();
foreach(var item in sorted)
{
sortedObservable.Add(item);
}
return sortedObservable;
}
要考虑字符串中的数值,您可以使用自定义比较器,The answer to this is a good example
这就是我最终解决问题的方法。在对象中,我连接了类型
public class TestObject{
public string type1{get; set;}
public string type2{get; set;}
public string type3{get; set;}
public string types{get;set;}
}
在填充 TestObjects 的方法中,我将其添加到:
public ObservableCollection<TestObject> TestObjects = new ObservableCollection<TestObject>();
TestObjects.Add(new TestObject('708','4','(A)','708.4.(A)'));
TestObjects.Add(new TestObject('7','41B','1(A)','7.41B.1(A)'));
TestObjects.Add(new TestObject('69','2','45', '69.2.45'));
TestObjects.Add(new TestObject('708','4','(B)', '708.4.(B)'));
TestObjects.Add(new TestObject('69','2','5', '69.2.5'));
TestObjects.Add(new TestObject('7','41','1(B)', '7.41.1(B)'));
TestObjects.Add(new TestObject('7','41','', '7.41.'));
TestObjects= SortObjects(TestObjects);
接下来,我在 ViewModel 中创建了一个自定义比较方法,使用 "Shlwapi.dll':
[DllImport("Shlwapi.dll", Charset = Charset.Unicode)]
private static extern int StrCmpLogicalW(string x, string y);
public ObservableCollection<TestObject> SortObjects(ObservableCollection<TestObject> unsortedObjects){
var sortedCollection = new ObservableCollection<TestObject>();
var objectList = new List<TestObject>();
foreach(var obj in unsortedObjects){
objectList.Add(obj);
}
Comparison<TestObject> typesComp = (a,b) =>{
var aKey = a.types;
var bKey = b.types;
return StrCmpLogicalW(aKey,bKey);
}
objectList.Sort(typesComp);
foreach(var obj in objectList){
sortedCollection.Add(obj);
}
return sortedCollection;
}
此方法允许我按升序 return TestObjects 集合。仍在研究降序开关,当我得到它时会更新它。
更新:这是具有反转能力的 SortObjects 方法
public ObservableCollection<TestObject> SortObjects(ObservableCollection<TestObject> unsortedObjects, bool IsAscend){
var sortedCollection = new ObservableCollection<TestObject>();
var objectList = new List<TestObject>();
foreach(var obj in unsortedObjects){
objectList.Add(obj);
}
Comparison<TestObject> typesComp = (a,b) =>{
var aKey = a.types;
var bKey = b.types;
return StrCmpLogicalW(aKey,bKey);
}
objectList.Sort(typesComp);
if(!isAscend){
objectsList.Reverse();
}
foreach(var obj in objectList){
sortedCollection.Add(obj);
}
return sortedCollection;
}
然后调用这样的真/假参数进行升序:
TestObjects = SortObjects(TestObjects, true);
降序排列如下:
TestObjects = SortObjects(TestObjects, false);