【发布时间】:2018-09-21 04:08:59
【问题描述】:
我试图找出删除模型(因此它是 VM)的最佳方法,尽管搜索了很多,但我还没有找到适合我的情况的令人满意的答案。
简化版本是,给定一个包含自身列表的模型,以及包含自身集合的后续视图模型,应该以什么顺序通知和删除事物?
我的工作假设是流程类似于
- 用户在子视图上单击删除
- 视图从父视图的数据上下文中调用 DeleteChild 命令,并将其自己的数据上下文作为参数传递
- 父虚拟机通知它的模型(父模型)它正在删除它的子虚拟机之一
- 父虚拟机从其集合中移除子虚拟机
- 父模型移除子模型
这似乎过于复杂,而且这种方法需要单独的逻辑来删除根项目,但是让视图调用它自己的 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>
如果不是乱七八糟,那肯定会令人困惑。
【问题讨论】: