在WP7中将List<T>转换为ObservableCollection<T>

78

不知道是太晚了还是怎么的,但我不知道如何做到这一点...

我想要做什么,而对象浏览器所显示的也是这样:

var oc = new ObservableCollection<T>( new List<T>() );

但是ObservableCollection<T>只有一个无参构造函数。对象浏览器显示有2个重载,其中应该可以传递List和IEnuerable。

我的设置有什么问题吗?构造函数在电话版本上不存在吗?(那会很奇怪)

如果这真的不存在,那现在WP7的标准方法是什么?

10个回答

170

ObservableCollection有几个构造函数,其中有输入参数为List<T>或IEnumerable<T>的:
List<T> list = new List<T>();
ObservableCollection<T> collection = new ObservableCollection<T>(list);


2
在Windows Phone 7上不行。 - Josh Close
2
今天(2019年4月29日)也使用了这个。这应该是有效的答案,特别是因为它使用了给定的SDK API中的“ObservableCollection”。@eugene.sushilnikov可能会获得大众化徽章;-) - Randika Vishman

50

显然,您的项目面向Windows Phone 7.0。不幸的是,接受IEnumerable<T>List<T>的构造函数在WP 7.0中不可用,只有无参数构造函数可用。其他构造函数可以在Silverlight 4及以上和WP 7.1及以上使用,但在WP 7.0中不可用。

我想您唯一的选择是将列表项逐个添加到新的ObservableCollection实例中,因为没有现成的方法来批量添加它们。尽管如此,这并不能阻止您将其放入扩展或静态方法中。

var list = new List<SomeType> { /* ... */ };
var oc = new ObservableCollection<SomeType>();
foreach (var item in list)
    oc.Add(item);

但是如果不必要,不要这样做,如果你的目标框架提供了重载函数,则使用它们。


很高兴在那个链接中看到了MSDN中的电话图标。太遗憾了,对象浏览器无法弄清楚它不可用。 - Josh Close
72
我宁愿停止编码也不想做那件事。 - Bastien Vandamme
3
使用这段代码:ObservableCollection<SomeType> oc = new ObservableCollection<SomeType>(list);创建一个泛型集合对象 oc,它属于 ObservableCollection<SomeType> 类型。这个集合包含了一个名为 list 的列表中的元素,并且能够自动通知相关部分其内容发生更改。 - Piero Alberto

20

要将List<T> list转换为可观察的集合,您可以使用以下代码:

var oc = new ObservableCollection<T>();
list.ForEach(x => oc.Add(x));

8
您需要编写自己的扩展方法来完成此操作:
    public static class CollectionEx
    {
      /// <summary>
      /// Copies the contents of an IEnumerable list to an ObservableCollection
      /// </summary>
      /// <typeparam name="T">The type of objects in the source list</typeparam>
      /// <param name="enumerableList">The source list to be converted</param>
      /// <returns>An ObservableCollection containing the objects from the source list</returns>
      public static ObservableCollection<T> ToObservableCollection<T>( this IEnumerable<T> enumerableList )
      {
        if( enumerableList != null ) {
          // Create an emtpy observable collection object
          var observableCollection = new ObservableCollection<T>();

          // Loop through all the records and add to observable collection object
          foreach( var item in enumerableList ) {
            observableCollection.Add( item );
          }

          // Return the populated observable collection
          return observableCollection;
        }
        return null;
      }
    }

7

这个IList<T>转换为ObservableCollection<T>的答案中提供的扩展方法非常有效。

public static ObservableCollection<T> ToObservableCollection<T>(this IEnumerable<T> enumerable) {
  var col = new ObservableCollection<T>();
  foreach ( var cur in enumerable ) {
    col.Add(cur);
  }
  return col;
}

2
另一个有用的扩展方法是AddRange。 - Nigel Sampson
再次惊讶于这个框架中还不存在的东西。实现起来相当容易,但可能需要到很多地方。我似乎总是要实现这个:IEnumerable<TSource>.Each( Action<TSource, int> predicate ) - Josh Close
@Josh Close:关于你的Each方法,请参见http://blogs.msdn.com/b/ericlippert/archive/2009/05/18/foreach-vs-foreach.aspx。 - Domenic
@Domenic:感谢你提供的链接!Lol:“显然,调用这种方法的唯一目的就是引起副作用”。这是真的。我同意他不应该在那里的原因。虽然我确实喜欢使用它,但你会遇到可能的闭包问题。JavaScript也是如此。 - Josh Close

6
请使用以下内容:
List<Class1> myList;
ObservableCollection<Class1> myOC = new ObservableCollection<Class1>(myList);

6
ObservableCollection<FacebookUser_WallFeed> result = new ObservableCollection<FacebookUser_WallFeed>(FacebookHelper.facebookWallFeeds);

2
如果您要添加大量项目,请考虑从ObservableCollection派生自己的类,并将项目添加到受保护的Items成员 - 这不会引发观察者中的事件。完成后,可以引发适当的事件:
public class BulkUpdateObservableCollection<T> : ObservableCollection<T>
{
    public void AddRange(IEnumerable<T> collection)
    {
        foreach (var i in collection) Items.Add(i);
        OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
        OnPropertyChanged(new PropertyChangedEventArgs("Count"));
    }
 }

当向已绑定到UI元素(如LongListSelector)的ObservableCollection中添加许多项时,这可能会产生巨大的性能差异。

在添加项目之前,您还可以确保有足够的空间,以便列表不会不断地通过在BulkObservableCollection类中实现此方法并在调用AddRange之前调用它来扩展:

    public void IncreaseCapacity(int increment)
    {
        var itemsList = (List<T>)Items;
        var total = itemsList.Count + increment;
        if (itemsList.Capacity < total)
        {
            itemsList.Capacity = total;
        }
    }

2

我制作了一个扩展,现在只需执行以下操作即可通过列表加载集合:

MyObservableCollection.Load(MyList);

这个扩展名是:

public static class ObservableCollectionExtension
{
  public static ObservableCollection<T> Load<T>(this ObservableCollection<T> Collection, List<T> Source)
  {
          Collection.Clear();    
          Source.ForEach(x => Collection.Add(x));    
          return Collection;
   }
}

0

Zin Min提供的答案用一行代码解决了我的问题。太棒了!

我遇到了同样的问题,需要将通用List转换为通用ObservableCollection,以使用List中的值来填充ComboBox,该ComboBox通过工厂类参与WPF窗口的绑定。

_expediteStatuses = new ObservableCollection<ExpediteStatus>(_db.getExpediteStatuses());

这是getExpediteStatuses方法的签名:

public List<ExpediteStatus> getExpediteStatuses()


请查看所有答案。没有一个像我的答案。我为你感到难过。 - Vítor Oliveira

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接