2012-07-25 67 views
1

我想按字母顺序排序ObservableCollection,因为我不想创建另一个绑定。我见过我们可以使用Linq和OrderBy方法。我还想使用个人IComparer,因为我将不得不组织复杂的数据(列表到其他列表),但VS告诉我我不能使用我自己的比较器:使用Linq和IComparer排序ObservableCollection

(给你错误的链接,因为我的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的新手)

回答

2

的这一问题线路在OrderBy的定义中,您尝试使用:

public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>(
    this IEnumerable<TSource> source, 
    Func<TSource, TKey> keySelector, 
    IComparer<TKey> comparer 
) 

该方法有两种不同的通用参数:TSourceTKeyTSource是显而易见的,它与源码IEnumerableTSource相同。 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操作从不更改源枚举,他们总是返回一个新的,转换的副本,而不是。

1

你的comparer比较GraphicObject。所以你OrderBy应该

GraphicObjects.OrderBy(graphicObject => graphicObject, 
               new GraphicObjectComparer(true)); 

或只使用

GraphicObjects.OrderBy(graphicObject => graphicObject.Nom); 

BTW,OrderBy不排序原地的,你应该将返回的IEnumerable<GraphicsObject>给一个变量

0

问题是你的比较器使用GraphicObject,但你比较字符串。

如果你真的需要自己的排序,你可以用这个的Comparer:

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; 
    } 
} 

或者你到你的比较器,而不是字符串提供GraphicObject。