2015-04-15 3 views
0

У меня есть наблюдаемая коллекция в моей модели ViewModel, привязанной к datagrid. Я хочу реализовать некоторую логику для обновления данных в других окнах на основе изменений в коллекции/обновлениях базы данных (используя LINQ to SQL).Коллекция ObservableCollection Измененное событие не срабатывает

Вот мой взгляд код модели:

public FTViewModel(int JobID) 
    { 
     _windowCloseAction = new DelegateCommand(OnWindowClose); 
     _oFTrn = new ObservableFilesTransmitted(_dataDc, JobID); 
     _oFTrn.CollectionChanged += oFTrnCollectionChanged; 
    } 

    void oFTrnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) 
    { 
     if (e.NewItems != null) 
     { 
      foreach (FilesTransmitted f in e.NewItems) 
       f.PropertyChanged += FilesTransmitted_PropertyChanged; 
     } 
     if (e.OldItems != null) 
     { 
      foreach (FilesTransmitted f in e.OldItems) 
       f.PropertyChanged -= FilesTransmitted_PropertyChanged; 
     } 
    } 

    void FilesTransmitted_PropertyChanged(object sender, PropertyChangedEventArgs e) 
    { 
     if (e.PropertyName == "DocumentNumber") 
     { 
      _filesTransmittedChange = true; 
     } 
     _refreshViews = true; 
    } 

и конструктор ObservableCollection:

class ObservableFilesTransmitted : ViewableCollection<FilesTransmitted> 
{ 
    public ObservableFilesTransmitted(DocControlDC dataDc, int ID) 
    { 
     foreach (FilesTransmitted ftran in dataDc.FilesTransmitteds.Where(x=>x.JobID==ID).OrderByDescending(x => x.TransmittalName)) 
     { 
      this.Add(ftran); 
     } 
    } 
} 

Отладчик не останавливается в oFTrnCollectionChanged. Я думаю, потому что вызов создания наблюдаемой коллекции происходит до того, как я добавлю событие CollectionChanged. Но, очевидно, я не могу переключить эти две линии. Я просмотрел различные темы StackOverflow и CodeProject, и мне кажется, что я должен работать. Нужно ли добавлять и удалять фиктивный элемент только для вызова обработчика CollectionChanged? Что мне не хватает?

Похоже, что у меня должен быть конструктор (для наблюдаемой коллекции), который не добавляет никаких членов, и функцию, которая добавляет элементы из базы данных. Затем я могу вызвать new, добавить обработчик collectionchanged, а затем заполнить коллекцию. Я надеюсь избежать этого уровня переписывания, хотя, возможно, это единственный разумный способ.

+0

коллекции должна наблюдаемой автоматически огонь.Пушку свойства изменено событие. –

ответ

1

Когда я подхожу к этому, самый простой способ его решить - просто подписаться вручную в начале.

public FTViewModel(int JobID) 
{ 
    _windowCloseAction = new DelegateCommand(OnWindowClose); 
    _oFTrn = new ObservableFilesTransmitted(_dataDc, JobID); 
    foreach(var item in _oFTrn) 
    { 
     item.PropertyChanged += FilesTransmitted_PropertyChanged; 
    } 
    _oFTrn.CollectionChanged += oFTrnCollectionChanged; 
} 

Однако даже лучшим решением является вместо того чтобы использовать класс, производный от ObserveableCollection<T> использовать класс, производный от BindingList<T>. Любой член повышения их события PropertyChanged заставит коллекцию поднять ListChanged с типом изменениями в ItemChanged

public FTViewModel(int JobID) 
{ 
    _windowCloseAction = new DelegateCommand(OnWindowClose); 
    _oFTrn = new ObservableFilesTransmitted(_dataDc, JobID); 
    _oFTrn.CollectionChanged += oFTrnListChanged; 
} 

void oFTrnListChanged(object sender, ListChangedEventArgs e) 
{ 
    if (e.ListChangedType == ListChangedType.ItemChanged) 
    { 
     if (e.PropertyDescriptor.Name == "DocumentNumber") 
     { 
      _filesTransmittedChange = true; 
     } 
    } 
    _refreshViews = true; 
} 
+0

лицоpalm. Конечно, я не уверен, почему я не сразу пошел по этому маршруту, хотя я оказался там после моего первоначального исправления (ниже). –

0

Я просто изменил конструктор ObservableCollection и добавлена ​​функция заселить:

Новый код вид модели:

public FTViewModel(int JobID) 
    { 
     _oFTrn = new ObservableFilesTransmitted(_dataDc, JobID); 
     _oFTrn.CollectionChanged += oFTrnCollectionChanged; 
     _oFTrn.FillCollection(); 

    } 

новый класс ObservableCollection:

class ObservableFilesTransmitted : ViewableCollection<FilesTransmitted> 
{ 
    DocControlDC _dc = null; 
    int _jobID = 0; 

    public ObservableFilesTransmitted(DocControlDC dataDc, int ID) 
    { 
     _dc = dataDc; 
     _jobID = ID; 
    } 

    public void FillCollection() 
    { 
     foreach (FilesTransmitted ftran in _dc.FilesTransmitteds.Where(x=>x.JobID==_jobID).OrderByDescending(x => x.TransmittalName)) 
     { 
      this.Add(ftran); 
     } 
    } 
} 

И все это работает, как ожидалось , Но он вызывается для каждого добавленного элемента. Я могу поиграть с идеей, что я просто перебираю коллекцию и добавляю обработчик propertychanged для каждого элемента в конструкторе viewmodel. Похоже, что это не так.

Смежные вопросы