2012-07-25 64 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。