c# - 如何在其父视图模型和模型的集合中删除视图模型和模型
问题描述
我试图找出删除模型(因此它是 VM)的最佳方法,尽管搜索了很多,但我还没有找到适合我的情况的令人满意的答案。
简化版本是,给定一个包含自身列表的模型,以及包含自身集合的后续视图模型,应该以什么顺序通知和删除事物?
我的工作假设是流程类似于
- 用户在子视图上单击删除
- 视图从父视图的 datacontext 调用 DeleteChild 命令,将它自己的 datacontext 作为参数传递
- 父虚拟机通知它的模型(父模型)它正在删除它的子虚拟机之一
- 父虚拟机从其集合中移除子虚拟机
- 父模型移除子模型
它看起来几乎过于复杂,并且此方法需要单独的逻辑来删除根项,但是让视图调用它自己的 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
}
视图模型
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>
如果它不凌乱,那肯定会令人困惑。
解决方案
- 用户在子视图上单击删除
- 视图从父视图的 datacontext 调用 DeleteChild 命令,将它自己的 datacontext 作为参数传递
- 父虚拟机通知它的模型(父模型)它正在删除它的子虚拟机之一
- 父虚拟机从其集合中移除子虚拟机
- 父模型移除子模型
差不多就是这样。我会补充
3a。模型广播一个关于它的一个孩子被移除的通知
因为视图模型不应该更改自己镜像模型集合的视图模型集合。推理:模型集合可能会在视图模型不做任何事情的情况下发生变化,因此无论如何它都必须对变化做出反应,并且您可以免费获得对源自视图模型的变化的反应。
推荐阅读
- reactjs - 如何解决 Apollo 的 Mutation 和 Formik Render Props 之间的相互依赖?
- ios - -Swift.h 头文件中没有名为“AVCaptureVideoDataOutputSampleBufferDelegate”的类型或协议
- angular - 我应该在我的 .ts 代码中添加什么以使 agm-info-window 工作?
- python - PySerial readline() 先返回命令,再返回答案
- reactjs - 流 - 事件类型中缺少属性
- amazon-web-services - 如何升级 Kops 版本
- sbt - 使用宏天堂并与 2.12/2.13 交叉编译
- node.js - 从nodejs中的数据库获取数据时的空值
- java - 如何将自定义键事件发送到小程序?
- python - 使用 Python 插件从 Python virtulenv 运行 VIM