如何在其父视图模型和模型的集合中删除视图模型和模型
How to delete a ViewModel and Model in a collection of it's parent's ViewModel and Model
我正在尝试找出删除模型(因此它是 VM)的最佳方法,尽管进行了相当多的搜索,但我还没有找到适合我的情况的满意答案。
简化版本是,给定一个包含自身列表的模型,以及包含自身集合的后续视图模型,应该以什么顺序通知和删除事物?
我的工作假设是流程是这样的
- 用户在子视图上单击删除
- 视图从父视图的数据上下文调用 DeleteChild 命令,将它自己的数据上下文作为参数传递
- 父 VM 通知它的模型(父模型)它正在删除它的一个子 VM
- 父 VM 从其集合中删除子 VM
- 父模型移除子模型
它似乎过于复杂,并且此方法需要单独的逻辑来删除根项,但是让视图调用它自己的 deleteself 命令将意味着列表和集合中的空项需要与父 VM 和模型进行通信。有没有 'typical' 删除模型的方法?
如果我现在必须写点什么,它看起来会像下面这样
型号
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>
如果它不凌乱,那肯定会令人困惑。
- User clicks delete on a child view
- The view calls the DeleteChild command from the parent view's datacontext, passing it's own datacontext as a parameter
- The parent VM notifies it's Model (the parent model) that it's deleting one of it's children's VMs
- The parent VM removes the child VM from it's collection
- The parent model removes the child model
差不多就这些了。我会添加
3a. the Model broadcasts a notification about one of its children being removed
因为视图模型不应更改自身镜像模型集合的视图模型集合。推理:模型集合很可能在视图模型不做任何事情的情况下发生变化,因此无论如何它都必须对变化做出反应,并且您可以免费获得对源自视图模型的变化的反应。
我正在尝试找出删除模型(因此它是 VM)的最佳方法,尽管进行了相当多的搜索,但我还没有找到适合我的情况的满意答案。
简化版本是,给定一个包含自身列表的模型,以及包含自身集合的后续视图模型,应该以什么顺序通知和删除事物?
我的工作假设是流程是这样的
- 用户在子视图上单击删除
- 视图从父视图的数据上下文调用 DeleteChild 命令,将它自己的数据上下文作为参数传递
- 父 VM 通知它的模型(父模型)它正在删除它的一个子 VM
- 父 VM 从其集合中删除子 VM
- 父模型移除子模型
它似乎过于复杂,并且此方法需要单独的逻辑来删除根项,但是让视图调用它自己的 deleteself 命令将意味着列表和集合中的空项需要与父 VM 和模型进行通信。有没有 'typical' 删除模型的方法?
如果我现在必须写点什么,它看起来会像下面这样
型号
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>
如果它不凌乱,那肯定会令人困惑。
- User clicks delete on a child view
- The view calls the DeleteChild command from the parent view's datacontext, passing it's own datacontext as a parameter
- The parent VM notifies it's Model (the parent model) that it's deleting one of it's children's VMs
- The parent VM removes the child VM from it's collection
- The parent model removes the child model
差不多就这些了。我会添加
3a. the Model broadcasts a notification about one of its children being removed
因为视图模型不应更改自身镜像模型集合的视图模型集合。推理:模型集合很可能在视图模型不做任何事情的情况下发生变化,因此无论如何它都必须对变化做出反应,并且您可以免费获得对源自视图模型的变化的反应。