2015-11-19 3 views
2

У меня есть ObservableCollection элементов, которые мне нужно иметь возможность обновлять и иметь все представленные данные с помощью ICollectionView.Ошибка: этот тип CollectionView не поддерживает изменения в SourceCollection

Вот соответствующие биты кода:

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"); 
} 

Вот 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; 
    } 

Я получаю следующее сообщение об ошибке в следующем фрагменте кода:

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.

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; 
} 

Ошибка происходит, когда у меня есть строка HeroesDB.Add (...), сразу после попытки catch.

Я пробовал массу вещей, ни одна из которых не сработала.

Я пробовал использовать другой ObservableCollection в качестве отфильтрованного списка и фильтровать его, но он все равно дает мне ошибку. Я попытался использовать MTObservableCollection и AsyncObservableCollection, взятые с первой страницы google, которые другие отправили, но они испортились и другими способами.

Как я могу заняться этим? Мне нужно иметь возможность фильтровать, мне нужна их коллекция, и когда исходный код изменяется, мне нужно сразу увидеть эти изменения в приложении.

+0

Ваша команда HeroesDBAddEntry вызывается потоком без GUI? – GazTheDestroyer

+0

Называется нажатие кнопки. Команда кнопки привязана к ней. – pingu2k4

+0

Я не хочу быть сердечным, но я рекомендую вам прочитать эту книгу. http://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882 –

ответ

6

Вы пробовали обернуть весь свой код, который устанавливает фильтр для вызова диспетчера WPF?

Обычно это нужно делать, если коллекция, связанная с представлением, изменяется в коде потока, отличного от потока пользовательского интерфейса.

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

Пробовал диспетчер несколькими способами, но всегда ударил ошибки. Я поместил код, который является ошибкой в ​​диспетчере, как вы указали, ошибка: «Необработанное исключение типа« System.NotSupportedException »произошло в PresentationFramework.dll Дополнительная информация: Этот тип CollectionView не поддерживает изменения в SourceCollection от нить, отличная от потока Диспетчера. ' – pingu2k4

+0

Странный. Я помню, что однажды я ошибся, как и ваш, при настройке фильтра «CollectionViewSource». Перемещение этого кода в диспетчер исправил его для меня. – Martin

+0

На какой строке кода вы получаете исключение? – Martin