Как удалить ViewModel и Model из коллекции ViewModel и Model его родителя - PullRequest
0 голосов
/ 21 сентября 2018

Я пытаюсь найти лучший способ удалить модель (и, следовательно, ее виртуальную машину), и, несмотря на то, что я довольно долго искал, я не нашел удовлетворительного ответа для своей ситуации.

Упрощенная версия, учитывая модель, которая содержит свой список, и ее последующую модель представления, которая содержит собственную коллекцию, в каком порядке следует уведомлять и удалять вещи?

Мое рабочее предположение состоит в том, что поток выглядит примерно так:

  1. Пользователь нажимает кнопку удаления в дочернем представлении
  2. Представление вызывает команду DeleteChild из текстового текста родительского представления.передавая свой собственный текстовый текст в качестве параметра
  3. Родительская виртуальная машина уведомляет свою модель (родительскую модель) об удалении одной из своих дочерних виртуальных машин
  4. Родительная виртуальная машина удаляет дочернюю виртуальную машину из своей коллекции
  5. Родительская модель удаляет дочернюю модель.

Кажется, что она слишком сложна, и для этого метода потребуется отдельная логика для удаления корневого элемента, однако наличие вызова 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>

Если это не грязно, это, безусловно, сбивает с толку.

1 Ответ

0 голосов
/ 21 сентября 2018
  1. Пользователь нажимает кнопку удалить в дочернем представлении
  2. Представление вызывает команду DeleteChild из контекста данных родительского представления, передавая свой собственный текст данных в качестве параметра
  3. Родительская виртуальная машинауведомляет свою модель (родительскую модель) об удалении одной из своих детских виртуальных машин
  4. родительская виртуальная машина удаляет дочернюю виртуальную машину из своей коллекции
  5. родительская модель удаляет дочернюю модель

Вот и все.Я бы добавил

3a.Модель передает уведомление об удалении одного из своих дочерних элементов

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

...