我想按字母顺序对ObservableCollection进行排序,因为我不想创建另一个绑定。我已经看到我们可以使用Linq和OrderBy方法。我也想使用一个个人的IComparer,因为我将不得不组织复杂的数据(列表到其他列表中),但是VS告诉我我不能使用自己的比较器:
(给您错误的链接,因为我的VS是法语的]
http://msdn.microsoft.com/en-gb/library/hxfhx4sy%28v=vs.90%29.aspx
任何想法?
private void SortGraphicObjectsAscending(object sender, RoutedEventArgs e)
{
GraphicObjects.OrderBy(graphicObject => graphicObject.Nom, new GraphicObjectComparer(true));
}
和我自己的比较器(已经过测试)
public class GraphicObjectComparer : IComparer<GraphicObject>
{
int order = 1;
public GraphicObjectComparer(Boolean ascending)
{
if (!ascending)
{
order = -1;
}
}
public GraphicObjectComparer()
{
}
public int Compare(GraphicObject x, GraphicObject y)
{
return String.Compare(x.Nom, y.Nom, false) * order;
}
}
感谢您的回答。无论如何,我还有另一个问题。正如迈克尔所说,我使用了一个更复杂的比较器,但用于另一个实体。该实体与分层树一起显示,并且一个对象可能包含相同类型的其他对象的列表。
我无法测试我的GraphicObject,因为我无权访问数据库(目前没有对象)。通过对我的VideoEntity的测试,我的ObservableCollection似乎没有按照我想要的方式排序(我创建了另一个)。我想按字母顺序反转它,但是它不起作用。
public class VideoEntityComparer : IComparer<VideoEntity>
{
int order = 1;
public VideoEntityComparer(Boolean ascending)
{
if (!ascending)
{
this.order = -1; // so descending
}
}
public VideoEntityComparer()
{
}
public int Compare(VideoEntity x, VideoEntity y)
{
if ((x is BaseDirectory && y is BaseDirectory) || (x is BaseSite && y is BaseSite) || (x is VideoEncoder && y is VideoEncoder))
{
return string.Compare(x.Nom, y.Nom, false) * order; // only objects of the same type are sorted alphabetically
}
else if ((x is BaseDirectory && y is BaseSite) || (x is BaseSite && y is VideoEncoder))
{
return -1;
}else
{
return 1;
}
}
}
private void SortDirectoriesDescending(object sender, RoutedEventArgs e)
{
ObservableCollection<BaseDirectory> tempDir = new ObservableCollection<BaseDirectory>(
Directories.OrderBy(directory => directory, new VideoEntityComparer(false)));
Directories = tempDir;
}
PS:顺便说一下,我正在处理DependancyProperty。这是正确的方法吗? (我是WPF的新手)
该行的问题在于您要使用的OrderBy
的定义:
public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector,
IComparer<TKey> comparer
)
此方法有两个不同的通用参数:TSource
和TKey
。 TSource
很明显,它与源TSource
的IEnumerable
相同。 TKey
参数是编译器正在尝试且未能进行推断的参数,因为您正在尝试使用两种不同的类型。您的电话:
GraphicObjects.OrderBy(graphicObject => graphicObject.Nom, new GraphicObjectComparer(true));
您的第一个参数是Func<GraphicObject, string>
,但是您的第二个参数是IComparer<GraphicObject>
;这表示您在一个地方使用TKey = string
,在另一个地方使用TKey = GraphicObject
。
第一个参数,即Func<>
委托,是“键选择器”;这就是您告诉OrderBy
要排序的值的方式。由于您的IComparer<>
是基于整个GraphicObject
实例进行排序的,因此应选择这作为键:
GraphicObjects.OrderBy(go => go, new GraphicObjectComparer(true));
我假设您的自定义比较器对象实际上比您显示的对象复杂,因为您的示例比较器非常多余:
var asc = GraphicObjects.OrderBy(go => go.Nom);
var desc = GraphicObjects.OrderByDescending(go => go.Nom);
[另外,请注意,您所使用的示例代码实际上并未对新排序的列表执行任何操作,因此它只是被扔掉了。 LINQ操作never更改可枚举的源,它们总是返回它的新的转换后的副本。
您的comparer
比较GraphicObject
。因此您的OrderBy
应该为
GraphicObjects.OrderBy(graphicObject => graphicObject,
new GraphicObjectComparer(true));
或仅使用
GraphicObjects.OrderBy(graphicObject => graphicObject.Nom);
顺便说一句,OrderBy
不能就地排序,您应该将返回的IEnumerable<GraphicsObject>
分配给变量
问题是您的比较器使用GraphicObject,但是您比较字符串。
如果您确实需要自己的订购,可以使用此比较器:
public class GraphicObjectComparer : IComparer<string>
{
int order = 1;
public GraphicObjectComparer(Boolean ascending)
{
if (!ascending)
{
order = -1;
}
}
public GraphicObjectComparer()
{
}
public int Compare(string x, string y)
{
return String.Compare(x, y, false) * order;
}
}
或者您将图形对象提供给比较器,而不是字符串。
为了对ObservableCollection进行排序,可以反映源集合中的所有更改,您可以使用我的ObservableComputations库。使用该库,您可以像这样编写代码:
var sortedGraphicObjects = GraphicObjects.Ordering(
graphicObject => graphicObject.Nom, new GraphicObjectComparer(true));
sortedGraphicObjects是ObservableCollection,并且反映了GraphicObjects集合和Nom属性中的所有更改。确保Nom属性通过INotifyPropertyChanged界面通知更改。