迭代编辑一个集合?

时间:2016-09-04 14:27:31

标签: c# wpf xaml

前言

我正在构建一个从互联网上抓取一些数据的应用程序。 需要实时更新数据,因此我运行无限循环 每次检查先前页面源是否更改。 所有这些数据都存储在ObservableCollection内,如下所示:

private static ObservableCollection<Models.Event> _allMatches = new ObservableCollection<Models.Event>();

public ObservableCollection<Models.Event> AllMatches
{
    get { return _matches; }
}

此O bservableCollection绑定在ListView中,如下所示:

<CollectionViewSource Source="{Binding AllMatches}" x:Key="GroupedItems">
    <CollectionViewSource.GroupDescriptions>
        <PropertyGroupDescription PropertyName="MatchNation" />
        <PropertyGroupDescription PropertyName="MatchLeague" />
    </CollectionViewSource.GroupDescriptions>
</CollectionViewSource>

CollectionViewSource帮助我使用ListView组织GroupStyle中的数据,在本例中为Nation -> League

问题开始

我将尝试创建一个简单的示例代码,以便更好地解释问题。因此,每个数据都被事件匹配,因此我基本上是ObservableCollection中的事件列表。

示例代码:

string oldData = null;
List<Event> matchListAll = new List<Event>();

while(true)
{
      string data = new WebClient().DownloadString("websiteLink");

      if(data != oldData) //There is an update! Get the new content
      {
            //code for scrape the event

            foreach(var item in ItemScraped)
            {
                  Event @event = new Event(); //this will contain the details of event scraped
                  @event.Date = item.Date; //and so on...

                  matchListAll.Add(@event); //Add the event to a list
            }

            //when the scraping iteration is over I put all of this event in the ObservableCollection
            AddAllListItem(matchListAll);
      }
}

现在上面的代码非常简单,从互联网上获取事件并将它们放入一个对象,就是这样。 当抓取完成后,我调用AddAllListItem,此方法将对ListView中绑定的ObservableCollection进行定值。

这种方法的结构如下:

private void AddAllListItem(List<Event> matches)
{
    var allCollection = VM.AllMatches; //Access to AllMatches through the Vm (VM contain the ViewModel instance)

    foreach (var @event in matches) //Iterate through the element scraped 
    {
        //Add the scraped element to ObservableCollection so I can see it.
        allCollection.Add(new Event 
        {
            MatchDate = @event.MatchDate,
            ...
        };
    }
}

此代码存在严重问题。我想有人已经知道会发生什么。

特别是我同时在方法AddAllListItem中添加ObservableCollection中的项目 再次调用,我作为参数传递的匹配项已更改。这将产生 例外:

  

收藏已修改。枚举操作可能无法执行。

如何解决这种情况?

我已经阅读了几个问题,这里有问题和其他建议使用.ToList.ToArray,但我有一个ObservableCollection,同时我在屏幕上显示元素我还需要更新他们。 我从来没有遇到过这样的情况,我希望有人帮助我解决这个问题 问题并解决它,谢谢。

1 个答案:

答案 0 :(得分:0)

也许这会对你有帮助。

public class AsyncObservableCollection<T> : ObservableCollection<T>
{
    private readonly object lockList = new object();

    public object LockList
    {
        get { return lockList; }
    } 

    public override event NotifyCollectionChangedEventHandler CollectionChanged;
    protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
    {
        var eh = CollectionChanged;
        if (eh != null)
        {
            Dispatcher dispatcher = (from NotifyCollectionChangedEventHandler nh in eh.GetInvocationList()
                                     let dpo = nh.Target as DispatcherObject
                                     where dpo != null
                                     select dpo.Dispatcher).FirstOrDefault();

            if (dispatcher != null && dispatcher.CheckAccess() == false)
            {
                dispatcher.Invoke(DispatcherPriority.DataBind, (Action)(() => OnCollectionChanged(e)));
            }
            else
            {
                foreach (NotifyCollectionChangedEventHandler nh in eh.GetInvocationList())
                    nh.Invoke(this, e);
            }
        }
    }

    new public void Remove(T item)
    {
        lock (lockList)
        {
            base.Remove(item);
        }
    }

    new public void Add(T item)
    {
        lock (lockList)
        {
            base.Add(item);
        }
    }

    public void AddByCheckExistence(T item)
    {
        lock (lockList)
        {
            if(!this.Contains(item))
            {
                base.Add(item);
            }
        }
    }
}