簡體   English   中英

使用 Linq 和 IComparer 對 ObservableCollection 進行排序

[英]Ordering ObservableCollection with Linq and IComparer

我想按字母順序排列一個 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
)

此方法有兩個不同的通用參數: TSourceTKey TSource很明顯,它與源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 操作永遠不會更改可枚舉的源,它們總是返回一個新的、轉換后的副本。

你的comparer比較GraphicObject 所以你的OrderBy應該是

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

或者只是使用

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

順便說一句, OrderBy不會就地排序,您應該將返回的IEnumerable<GraphicsObject>分配給一個變量

問題是您的 Comparer 使用 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;
    }
}

或者您向比較器提供一個 GraphicObject,而不是字符串。

為了排序 ObservableCollection 反映源集合中的所有更改,您可以使用我的ObservableComputations庫。 使用此庫,您可以編寫如下代碼:

var sortedGraphicObjects = GraphicObjects.Ordering(
    graphicObject => graphicObject.Nom, new GraphicObjectComparer(true));

sortedGraphicObjects 是 ObservableCollection,反映了 GraphicObjects 集合和 Nom 屬性中的所有變化。 確保 Nom 屬性通過INotifyPropertyChanged接口通知更改。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM