Я пытаюсь найти лучший способ удалить модель (и, следовательно, ее виртуальную машину), и, несмотря на то, что я довольно долго искал, я не нашел удовлетворительного ответа для своей ситуации.
Упрощенная версия, учитывая модель, которая содержит свой список, и ее последующую модель представления, которая содержит собственную коллекцию, в каком порядке следует уведомлять и удалять вещи?
Мое рабочее предположение состоит в том, что поток выглядит примерно так:
- Пользователь нажимает кнопку удаления в дочернем представлении
- Представление вызывает команду DeleteChild из текстового текста родительского представления.передавая свой собственный текстовый текст в качестве параметра
- Родительская виртуальная машина уведомляет свою модель (родительскую модель) об удалении одной из своих дочерних виртуальных машин
- Родительная виртуальная машина удаляет дочернюю виртуальную машину из своей коллекции
- Родительская модель удаляет дочернюю модель.
Кажется, что она слишком сложна, и для этого метода потребуется отдельная логика для удаления корневого элемента, однако наличие вызова view собственной команды deleteself будет означать nullэлементы в списке и коллекции, требующие связи с родительской виртуальной машиной и моделью.Есть ли «типичный» способ удаления моделей?
Если бы мне пришлось написать что-то прямо сейчас, это выглядело бы следующим образом
Модель
public class NestingBoxModel
{
public NestingBoxModel()
{
NestingBoxModels = new List<NestingBoxModel>();
}
public List<NestingBoxModel> NestingBoxModels { get; }
public Boolean ShouldBeRemoved { get; private set; }
/// <summary>
/// Notfies child to prepare for removal
/// </summary>
/// <param name="child">Child to be notified</param>
public void DeleteChild(NestingBoxModel child)
{
NestingBoxModels.Find(c => c == child)?.PrepareForRemoval();
}
/// <summary>
/// Notifes all children to prepare for removal
/// Marked as ready for removal
/// </summary>
public void PrepareForRemoval()
{
NestingBoxModels.ForEach(nb => nb.PrepareForRemoval());
ShouldBeRemoved = true;
}
// Other stuff for saving and eventually removing the model
}
ViewModel
public class NestingBoxViewModel : BindableBase
{
public NestingBoxViewModel()
{
Model = new NestingBoxModel();
ViewModels = new ObservableCollection<NestingBoxViewModel>();
DeleteChildCommand = new DelegateCommand<object>(DeleteChild);
DeleteCommand = new DelegateCommand(PrepareForRemoval);
}
public NestingBoxModel Model { get; private set; }
public ObservableCollection<NestingBoxViewModel> ViewModels { get; private set; }
public ICommand DeleteChildCommand { get; }
public ICommand DeleteCommand { get; }
/// <summary>
/// Finds, notifies, and removes child viewmodel
/// </summary>
/// <param name="child">Child viewmodel to be removed</param>
private void DeleteChild(object child)
{
var matchingchild = ViewModels.First<NestingBoxViewModel>(vm => vm.Equals(child));
if (matchingchild != null)
{
Model.DeleteChild(matchingchild.Model);
ViewModels.Remove(matchingchild);
matchingchild.PrepareForRemoval();
}
}
/// <summary>
/// Prepares for garbage collection
/// </summary>
public void PrepareForRemoval()
{
ViewModels.ToList<NestingBoxViewModel>().ForEach(vm => vm.PrepareForRemoval());
Model = null;
ViewModels = null;
}
}
Просмотр
<Border Width="5">
<StackPanel Margin="10">
<Button Content="New NestingBox" Command="{Binding DeleteChildCommand, RelativeSource={RelativeSource TemplatedParent}}" CommandParameter="{Binding}"/>
<ItemsControl ItemsSource="{Binding ViewModels}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:NestingBoxView/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</Border>
Если это не грязно, это, безусловно, сбивает с толку.