wpf 错误:这种类型的 CollectionView 不支持对其 SourceCollection 的更改

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/33808346/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 13:33:02  来源:igfitidea点击:

Error: This type of CollectionView does not support changes to its SourceCollection

c#wpfmvvmobservablecollectioncollectionviewsource

提问by pingu2k4

I have an ObservableCollection of items, which I need to be able to update and have the data represented still using an ICollectionView.

我有一个 ObservableCollection 项目,我需要能够更新并使用 ICollectionView 表示数据。

Here are relevant bits of code:

以下是相关代码:

private ObservableCollection<Hero> heroesDBHeroes;
public ObservableCollection<Hero> HeroesDBHeroes
{
    get
    {
        return heroesDBHeroes;
    }
    set
    {
        heroesDBHeroes = value;
        OnPropertyChanged("HeroesDBHeroes");
    }
}
private void HeroesDBAddHeroes()
{
    if(HeroesDBHeroes != null)
    {
        HeroesDBHeroes.Clear();
    }
    HeroesDBHeroes = Hero.GetAllHeroes();

    HeroesDBFilteredHeroes = new ListCollectionView(HeroesDBHeroes);
    HeroesDBFilteredHeroes.Filter = new Predicate<object>(HeroesDBFilterHeroes);
    HeroesDBFilteredHeroes.Refresh();
    OnPropertyChanged("HeroesDBFilteredHeroes");
}

Here is the CollectionView and its filter:

这是 CollectionView 及其过滤器:

    public CollectionView HeroesDBFilteredHeroes { get; set; }
    public bool HeroesDBFilterHeroes(object item)
    {
        Hero h = item as Hero;
        bool ID, Name, GoldMinimum, GoldMaximum, PlatinumMinimum, PlatinumMaximum, DBTag, ReleaseDateStart, ReleaseDateEnd, Available, Sale, Featured, New, F2P, Homepage, Thumbnail, FeaturedThumbnail, ShortDescription, Description;

        ID = Name = GoldMinimum = GoldMaximum = PlatinumMinimum = PlatinumMaximum = DBTag = ReleaseDateStart = ReleaseDateEnd = Available = Sale = Featured = New = F2P = Homepage = Thumbnail = FeaturedThumbnail = ShortDescription = Description = false;

        if (h == null)
        {
            return false;
        }

        if (HeroesDBFilterID == null || HeroesDBFilterID == h.ID)
        {
            ID = true;
        }

        if (HeroesDBFilterName == "" || h.Name.IndexOf(HeroesDBFilterName, 0, StringComparison.CurrentCultureIgnoreCase) != -1)
        {
            Name = true;
        }

        if (HeroesDBFilterGoldMinimum == null || HeroesDBFilterGoldMinimum <= h.Gold)
        {
            GoldMinimum = true;
        }

        if (HeroesDBFilterGoldMaximum == null || HeroesDBFilterGoldMaximum >= h.Gold)
        {
            GoldMaximum = true;
        }

        if (HeroesDBFilterPlatinumMinimum == null || HeroesDBFilterPlatinumMinimum <= h.Platinum)
        {
            PlatinumMinimum = true;
        }

        if (HeroesDBFilterPlatinumMaximum == null || HeroesDBFilterPlatinumMaximum >= h.Platinum)
        {
            PlatinumMaximum = true;
        }

        if (HeroesDBFilterDBTag == "" || h.DBTag.IndexOf(HeroesDBFilterDBTag, 0, StringComparison.CurrentCultureIgnoreCase) != -1)
        {
            DBTag = true;
        }

        if (HeroesDBFilterReleaseDateStart == null || HeroesDBFilterReleaseDateStart <= h.ReleaseDate)
        {
            ReleaseDateStart = true;
        }

        if (HeroesDBFilterReleaseDateEnd == null || HeroesDBFilterReleaseDateEnd >= h.ReleaseDate)
        {
            ReleaseDateEnd = true;
        }

        switch(HeroesDBFilterAvailable)
        {
            case 0:
                Available = true;
                break;
            case 1:
                if(h.Available == true)
                {
                    Available = true;
                }
                break;
            case 2:
                if (h.Available == false)
                {
                    Available = true;
                }
                break;
        }

        switch (HeroesDBFilterSale)
        {
            case 0:
                Sale = true;
                break;
            case 1:
                if (h.Sale == true)
                {
                    Sale = true;
                }
                break;
            case 2:
                if (h.Sale == false)
                {
                    Sale = true;
                }
                break;
        }

        switch (HeroesDBFilterFeatured)
        {
            case 0:
                Featured = true;
                break;
            case 1:
                if (h.Featured == true)
                {
                    Featured = true;
                }
                break;
            case 2:
                if (h.Featured == false)
                {
                    Featured = true;
                }
                break;
        }

        switch (HeroesDBFilterNew)
        {
            case 0:
                New = true;
                break;
            case 1:
                if (h.NewTag == true)
                {
                    New = true;
                }
                break;
            case 2:
                if (h.NewTag == false)
                {
                    New = true;
                }
                break;
        }

        switch (HeroesDBFilterF2P)
        {
            case 0:
                F2P = true;
                break;
            case 1:
                if (h.F2P == true)
                {
                    F2P = true;
                }
                break;
            case 2:
                if (h.F2P == false)
                {
                    F2P = true;
                }
                break;
        }

        switch (HeroesDBFilterHomepage)
        {
            case 0:
                Homepage = true;
                break;
            case 1:
                if (h.Homepage == true)
                {
                    Homepage = true;
                }
                break;
            case 2:
                if (h.Homepage == false)
                {
                    Homepage = true;
                }
                break;
        }

        switch (HeroesDBFilterThumbnail)
        {
            case 0:
                Thumbnail = true;
                break;
            case 1:
                if (h.ThumbnailImage.Count<byte>() >= 5)
                {
                    Thumbnail = true;
                }
                break;
            case 2:
                if (h.ThumbnailImage.Count<byte>() < 5)
                {
                    Thumbnail = true;
                }
                break;
        }

        switch (HeroesDBFilterFeaturedThumbnail)
        {
            case 0:
                FeaturedThumbnail = true;
                break;
            case 1:
                if (h.FeaturedThumbnailImage.Count<byte>() >= 5)
                {
                    FeaturedThumbnail = true;
                }
                break;
            case 2:
                if (h.FeaturedThumbnailImage.Count<byte>() < 5)
                {
                    FeaturedThumbnail = true;
                }
                break;
        }

        if (HeroesDBFilterShortDescription == "" || h.ShortDescription.IndexOf(HeroesDBFilterShortDescription, 0, StringComparison.CurrentCultureIgnoreCase) != -1)
        {
            ShortDescription = true;
        }

        if (HeroesDBFilterDescription == "" || h.Description.IndexOf(HeroesDBFilterDescription, 0, StringComparison.CurrentCultureIgnoreCase) != -1)
        {
            Description = true;
        }

        return ID && Name && GoldMinimum && GoldMaximum && PlatinumMinimum && PlatinumMaximum && DBTag && ReleaseDateStart && ReleaseDateEnd && Available && Sale && Featured && New && F2P && Homepage && Thumbnail && FeaturedThumbnail && ShortDescription && Description;
    }

I get the following error in the following code snippet:

我在以下代码片段中收到以下错误:

An unhandled exception of type 'System.NotSupportedException' occurred in PresentationFramework.dll

Additional information: This type of CollectionView does not support changes to its SourceCollection from a thread different from the Dispatcher thread.

PresentationFramework.dll 中发生类型为“System.NotSupportedException”的未处理异常

附加信息:这种类型的 CollectionView 不支持从不同于 Dispatcher 线程的线程更改其 SourceCollection。

private ICommand heroesDBAddEntry;
public ICommand HeroesDBAddEntry
{
    get
    {
        if (heroesDBAddEntry == null)
        {
            heroesDBAddEntry = new RelayCommand(HeroesDBAddEntryEx, null);
        }
        return heroesDBAddEntry;
    }
}
private void HeroesDBAddEntryEx(object p)
{
    if (HeroesDBUpdateID != null)
    {
        HeroesDBUpdateEntryEx();
        return;
    }

    int x;
    var db = new SQLiteDatabase();

    string query, changesQuery;

    query = "INSERT INTO Heroes (Name,Description,ShortDescription,Gold,Platinum,DBTag,ReleaseDate,Available,Sale,Featured,NewTag,F2P,Homepage,ThumbnailImage,ThumbnailImageName," +
        "FeaturedThumbnailImage,FeaturedThumbnailImageName) ";

    query += "VALUES ('" + HeroesDBName.Replace("'", "''") + "','" + HeroesDBDescription.Replace("'", "''") + "','" + HeroesDBShortDescription.Replace("'", "''") + "'," +
        HeroesDBGold + "," + HeroesDBPlatinum + ",'" + HeroesDBDBTag.Replace("'", "''") + "','" + HeroesDBReleaseDate.Date.ToString("yyyy-MM-dd") + "'," +
        Convert.ToInt32(HeroesDBAvailable) + "," + Convert.ToInt32(HeroesDBSale) + "," + Convert.ToInt32(HeroesDBFeatured) + "," + Convert.ToInt32(HeroesDBNewTag) + "," +
        Convert.ToInt32(HeroesDBF2P) + "," + Convert.ToInt32(HeroesDBHomepage) + ",'" + Convert.ToBase64String(HeroesDBThumbnailImage) + "','" +
        HeroesDBThumbnailPath.Replace("'", "''") + "','" + Convert.ToBase64String(HeroesDBFeaturedThumbnailImage) + "','" + HeroesDBFeaturedThumbnailPath.Replace("'", "''") + "'); ";

    changesQuery = "INSERT INTO Heroes_Changes (HeroID,Action,TimeStamp,User,Name,Description,ShortDescription,Gold,Platinum,DBTag,ReleaseDate,Available,Sale,Featured,NewTag,F2P," +
        "Homepage,ThumbnailImage,ThumbnailImageName,FeaturedThumbnailImage,FeaturedThumbnailImageName) ";

    changesQuery += "VALUES (" + HeroesDBNextID + ",'" + "INSERT" + "','" + DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss") + "','" + Environment.UserName + "','" +
        HeroesDBName.Replace("'", "''") + "','" + HeroesDBDescription.Replace("'", "''") + "','" + HeroesDBShortDescription.Replace("'", "''") + "'," +
        HeroesDBGold + "," + HeroesDBPlatinum + ",'" + HeroesDBDBTag.Replace("'", "''") + "','" + HeroesDBReleaseDate.Date.ToString("yyyy-MM-dd") + "'," +
        Convert.ToInt32(HeroesDBAvailable) + "," + Convert.ToInt32(HeroesDBSale) + "," + Convert.ToInt32(HeroesDBFeatured) + "," + Convert.ToInt32(HeroesDBNewTag) + "," +
        Convert.ToInt32(HeroesDBF2P) + "," + Convert.ToInt32(HeroesDBHomepage) + ",'" + Convert.ToBase64String(HeroesDBThumbnailImage) + "','" +
        HeroesDBThumbnailPath.Replace("'", "''") + "','" + Convert.ToBase64String(HeroesDBFeaturedThumbnailImage) + "','" + HeroesDBFeaturedThumbnailPath.Replace("'", "''") + "'); ";

    try
    {
        x = db.ExecuteNonQuery(query);
        HeroesDBStatus = x + " Record(s) Added.";
        x = db.ExecuteNonQuery(changesQuery);
    }
    catch(Exception err)
    {
        System.Windows.Forms.MessageBox.Show(err.Message);
    }

    HeroesDBHeroes.Add(new Hero(
        HID: HeroesDBNextID,
        HName: HeroesDBName,
        HDescription: HeroesDBDescription,
        HShortDescription: HeroesDBShortDescription,
        HGold: HeroesDBGold,
        HPlatinum: HeroesDBPlatinum,
        HDBTag: HeroesDBDBTag,
        HReleaseDate: HeroesDBReleaseDate,
        HAvailable: HeroesDBAvailable,
        HSale: HeroesDBSale,
        HFeatured: HeroesDBFeatured,
        HNewTag: HeroesDBNewTag,
        HF2P: HeroesDBF2P,
        HHomepage: HeroesDBHomepage,
        HThumbnailImage: HeroesDBThumbnailImage,
        HThumbnailImageName: HeroesDBThumbnailPath,
        HFeaturedThumbnailImage: HeroesDBFeaturedThumbnailImage,
        HFeaturedThumbnailImageName: HeroesDBFeaturedThumbnailPath,
        HForce: true
        ));
    HeroesDBNextID++;

    HeroesDBName = "";
    HeroesDBDescription = "";
    HeroesDBShortDescription = "";
    HeroesDBGold = 0;
    HeroesDBPlatinum = 0;
    HeroesDBDBTag = "";
    HeroesDBReleaseDate = DateTime.Today;
    HeroesDBAvailable = false;
    HeroesDBSale = false;
    HeroesDBFeatured = false;
    HeroesDBNewTag = false;
    HeroesDBF2P = false;
    HeroesDBHomepage = false;
    HeroesDBThumbnailImage = new byte[] { 0x00 };
    HeroesDBThumbnailPath = "";
    HeroesDBFeaturedThumbnailImage = new byte[] { 0x00 };
    HeroesDBFeaturedThumbnailPath = "";
    HeroesDBUpdateID = null;
}

The error happens where I have the HeroesDB.Add(...) line, just after the try catch.

错误发生在我有 HeroesDB.Add(...) 行的地方,就在 try catch 之后。

I have tried a ton of things, none of which have worked.

我尝试了很多东西,但都没有奏效。

I have tried using another ObservableCollection as the filtered list and filtering that, but it still gives me an error. I have tried using MTObservableCollection and AsyncObservableCollection taken from the first page of google which others have posted, but they mess up in other ways as well.

我尝试使用另一个 ObservableCollection 作为过滤列表并过滤它,但它仍然给我一个错误。我曾尝试使用 MTObservableCollection 和 AsyncObservableCollection 取自其他人发布的谷歌第一页,但它们也以其他方式搞砸了。

How would I go about tackling this one? I need to be able to filter, I need a collection of them, and when the source changes I need to see those changes in the app right away.

我将如何处理这个问题?我需要能够过滤,我需要它们的集合,当源发生变化时,我需要立即在应用程序中看到这些变化。

回答by Martin

Have you tried wrapping all your code which sets up the filter to a call to the WPF dispatcher?

您是否尝试将所有设置过滤器的代码包装为对 WPF 调度程序的调用?

Generally this has to be done if the collection bound to the view is modified in code of a thread different than the UI thread.

通常,如果绑定到视图的集合在不同于 UI 线程的线程的代码中被修改,则必须这样做。

Application.Current.Dispatcher.BeginInvoke(
  DispatcherPriority.Background,
  new Action(() => { 
    HeroesDBAddHeroes();
  }));