Не создавайте новую коллекцию после каждого удаления. Это отрицательно скажется на производительности. Это причина, по которой вы используете ObservableCollection
. Таким образом, цель привязки, например, ListBox
, может обновлять только измененные элементы, вместо воссоздания / рендеринга полного представления.
В этом контексте также не имеет смысла раскрывать данные исходный код ICollectionsView
. Скорее привязывайтесь к ObservableCollection
напрямую.
Когда исходная коллекция ICollectionsView
реализует INotifyCollectionChanged
, как ObservableCollection<T>
, тогда ICollectionView
будет автоматически обновляться при изменении источника. В этом случае достаточно манипулировать коллекцией INotifyCollectionChanged
.
Когда исходная коллекция ICollectionsView
не реализует INotifyCollectionChanged
как List<T>
, тогда ICollectionView
не будет автоматически обновляться при изменении источника. В этом случае вы должны явно вызвать ICollectionView.Refresh
, чтобы принудительно обновить ICollectionView
.
Обратите внимание, что никогда не должны ссылаться на какие-либо компоненты представления в вашей модели представления - без исключений. Это исключает все преимущества MVVM. И это наверняка никогда не нужно. Если ваша модель представления требует ссылки на компонент представления, вы неправильно проектируете свой код или классы. Чтобы следовать этому основному c и фундаментальному правилу проектирования MVVM, вы должны удалить ссылку на Window
из HomeViewModel
. Вы можете инициировать поведение представления, выставив свойство в модели представления, которое является входом для триггера данных в представлении. Шаблоны - приложения WPF с шаблоном проектирования Model-View-ViewModel , Шаблон Model-View-ViewModel .
Первое решение (рекомендуется)
Вы должны напрямую привязаться к коллекции Tasks
. В тот момент, когда вам нужно манипулировать представлением коллекции, например, чтобы применить фильтр, выберите представление, используя CollectionViewSource.GetDefaultView(Tasks)
. Но не привязывайтесь к нему.
<ListBox ItemsSource="{Binding Tasks}" />
public HomeViewModel()
{
Tasks = new ObservableCollection<TaskModel>(_context.Task);
Tasks.CollectionChanged += OnTasksChanged;
}
private void OnTasksChanged(object sender, NotifyCollectionChangedEventArgs e)
{
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
{
foreach (TaskModel task in e.NewItems)
{
_context.Task.Add(task);
_context.SaveChanges();
}
break;
}
case NotifyCollectionChangedAction.Remove:
{
foreach (TaskModel task in e.OldItems)
{
_context.Task.Attach(task);
_context.Task.Remove(task);
_context.SaveChanges();
}
break;
}
}
}
// Then simply manipulate the 'Tasks' collection
public ICommand DeleteTaskCommand => new DelegateCommand(() => Tasks.Remove(SelectTask));
Второе решение
Если вы хотите выполнить привязку к ICollectionView
, вам больше не нужен дополнительный ObservableCollection
(кроме вас хотите поддерживать две коллекции и ICollectionView
при каждой операции добавления / перемещения / удаления / сброса). Чтобы обновить представление коллекции, вызовите ICollectionView.Refresh
.
<ListBox ItemsSource="{Binding TasksView}" />
public HomeViewModel()
{
TasksView = CollectionViewSource.GetDefaultView(_context.Task);
}
// Then simply refresh the 'TasksView':
public ICommand DeleteTask => DelegateCommand(
() =>
{
_context.Task.Attach(SelectTask);
_context.Task.Remove(SelectTask);
_context.SaveChanges();
// Update the view
TasksView.Refresh();
});