【问题标题】:How to cope with an Observable collection of classes如何处理 Observable 类集合
【发布时间】:2016-05-31 09:23:09
【问题描述】:

我有以下 TracefieldPartProgramClass

public class TracefieldPartProgramClass
{
    public TracefieldPartProgramClass() { }
    public ObservableCollection<Tuple<string, object, object>> obcTraceFieldPartProgram = new ObservableCollection<Tuple<string, object, object>>();
}

我用它来制作以下收藏:

ObservableCollection<EasyRunBinSerializableData.TracefieldPartProgramClass>();

现在,在填写完之后,我希望能够按我的意愿进行排序(比如在 Tracefield[0] 上)。 所以我实现了这个:

private ObservableCollection<EasyRunBinSerializableData.TracefieldPartProgramClass> SortOnTracefield(ObservableCollection<EasyRunBinSerializableData.TracefieldPartProgramClass> obcToSort)
{
var obcSorted = new ObservableCollection<EasyRunBinSerializableData.TracefieldPartProgramClass>();
obcSorted = obcToSort.OrderBy(w => w.obcTraceFieldPartProgram[0].Item3.ToString());<--- this is where I get the error
return obcSorted;

}

但是当我这样做时,我得到了这个错误:

错误 CS0266 无法将类型“System.Linq.IOrderedEnumerable”隐式转换为“System.Collections.ObjectModel.ObservableCollection”。存在显式转换(您是否缺少演员表?)

【问题讨论】:

    标签: c# linq sorting observablecollection


    【解决方案1】:

    试试这个:

    private ObservableCollection<EasyRunBinSerializableData.TracefieldPartProgramClass> SortOnTracefield(ObservableCollection<EasyRunBinSerializableData.TracefieldPartProgramClass> obcToSort)
    {
        var sorted = obcToSort.OrderBy(w => w.obcTraceFieldPartProgram[0].Item3.ToString();
        return new ObservableCollection<EasyRunBinSerializableData.TracefieldPartProgramClass>(sorted);
    }
    

    您可以将 IEnumerable 传递给可观察集合的构造函数。


    但是,这会返回集合的新实例。因此,如果未排序的实例绑定到 GUI,则可能不会更新您的 GUI。另一种支持排序的方法是使用ICollectionView


    SO 问题how-do-i-sort-an-observable-collection 对您来说可能也很有趣。以下扩展方法可用于对ObservableCollections 进行排序,无需重新创建:

    static class Extensions
    {
        public static void Sort<T>(this ObservableCollection<T> collection) where T : IComparable
        {
            List<T> sorted = collection.OrderBy(x => x).ToList();
            for (int i = 0; i < sorted.Count(); i++)
                collection.Move(collection.IndexOf(sorted[i]), i);
        }
    }
    

    但是,您的 TracefieldPartProgramClass 类需要实现 IComparable 或者您需要实现自定义 IComparer&lt;TracefieldPartProgramClass&gt; 并将其传递给 Sort 方法。

    【讨论】:

      【解决方案2】:

      正如错误所说,您试图将IOrderedEnumerable 分配给ObservableCollection 类型的变量,这是不可能的。

      但幸运的是,ObservableCollection 有一个 constructor,它接受一个 IEnumerable 并用 IEnumerable 的项目预填充它。

      因此,为了使该错误消失,请使用:

      var sortedEnumerable = obcToSort.OrderBy(w => w.obcTraceFieldPartProgram[0].Item3.ToString());
      obcSorted = new ObservableCollection<EasyRunBinSerializableData.TracefieldPartProgramClass>(sortedEnumerable );
      

      【讨论】:

        【解决方案3】:

        Enumerable.OrderBy 不返回ObservableCollection,而是返回IEnumerable&lt;T&gt;,您可以使用List&lt;T&gt; constructor 创建一个新的:

        var obcSortedList = obcToSort
            .OrderBy(w => w.obcTraceFieldPartProgram[0].Item3.ToString())
            .ToList();  
        var obcSorted = new ObservableCollection<EasyRunBinSerializableData.TracefieldPartProgramClass>(obcSortedList);
        

        【讨论】:

        • 为什么使用 IList 构造函数而不是 IEnumerable 构造函数?这对性能有什么好处吗?
        • @Domysee:List&lt;T&gt; constructor 是一个空操作,IEnumerable&lt;T&gt; 构造函数将通过枚举所有元素来创建一个列表。所以你可以同时使用。
        • 不过 List&lt;T&gt; 构造函数也会创建传递列表 (source) 的副本,所以 IEnumerable&lt;T&gt; 构造函数看起来更适合我。
        • @IvanStoev:还没有看到关于 VSWhidbey 错误 562681 的评论,所以你是对的。如果我还没有列表,我也更喜欢IEnumerable&lt;T&gt; 构造函数。
        猜你喜欢
        • 1970-01-01
        • 2020-12-21
        • 1970-01-01
        • 2014-07-21
        • 1970-01-01
        • 2022-01-17
        • 1970-01-01
        • 2020-02-05
        • 1970-01-01
        相关资源
        最近更新 更多