如何删除其父级的ViewModel和模型集合中的ViewModel和模型

时间:2018-09-21 04:08:59

标签: c# wpf mvvm prism

我正在尝试找出删除模型的最佳方法(因此是VM),尽管进行了很多搜索,但我仍未找到满意的答案。

给定简化模型,给定一个包含自身列表的模型,以及随后的包含自身集合的viewmodel,应该以什么顺序通知和删除事物?

我的工作假设是流程类似

  1. 用户点击子视图上的删除
  2. 该视图从父视图的数据上下文中调用DeleteChild命令,并将其自身的数据上下文作为参数传递
  3. 父VM通知其Model(父模型)正在删除其子VM之一
  4. 父VM从其集合中删除子VM
  5. 父模型删除子模型

这似乎过于复杂,此方法将需要单独的逻辑来删除根项目,但是,如果具有视图调用它自己的deleteself命令,则意味着列表和集合中的空项目必须与父VM和模型进行通信。有删除模型的“典型”方法吗?

如果我现在必须写点东西,它将如下所示

模型

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 :(得分:1)

  
      
  1. 用户点击子视图上的删除
  2.   
  3. 该视图从父视图的数据上下文中调用DeleteChild命令,并将其自身的数据上下文作为参数传递
  4.   
  5. 父VM通知其Model(父模型)正在删除其子VM之一
  6.   
  7. 父VM从其集合中删除子VM
  8.   
  9. 父模型删除子模型
  10.   

就是这样。我要添加

  

3a。该模型广播有关其子级之一被删除的通知

因为视图模型不应更改自己镜像模型集合的视图模型集合。推理:模型集合很可能在没有视图模型做任何事情的情况下发生更改,因此无论如何它都必须对更改做出反应,并且您可以免费获得对源自视图模型的更改的响应。