想象一个简单的场景,WPF窗口包含一个按钮和一些空白区域。单击该按钮可创建一个新的自定义/用户控件,并将其随机放置在窗口上。
单击其中一个控件将其从窗口中删除。
所以现在我有了一个ViewModel ala MVVM,它为“创建新”按钮公开了一个ICommand,但创建新控件的代码在哪里生效?每个控件可能都有自己的ViewModel,它可以处理它的删除和定位。
可以在窗口上没有代码的情况下实现它并且ViewModel对View没有真正的了解吗?
答案 0 :(得分:1)
对于ItemsControl上的一些非常小心的数据绑定,这应该是可行的,不知道如何实现布局,但是你将拥有一个包含子视图模型集合的父视图模型,然后由ItemsControl执行布局。当父ViewModel创建子ViewModel时,它应该将一个RelayCommand注入一个lambda表达式,以从父集合中删除和清除子ViewModel。
答案 1 :(得分:1)
导致创建控件的代码存在于“主”ViewModel中。
实际创建控件的代码是容器。
所以它会像:
void AddControlCommandExecuted() {
var container = // resolve your DI container here
// Now use the container to resolve your "child" view. For example,
// if using UnityContainer it could go like this:
var view = container.Resolve<ChildView>();
// Of course you can also resolve the ViewModel if your program is
// "ViewModel-first" instead of "View-first".
// Does the ChildViewModel need some properties to be set?
var viewModel = (ChildViewModel)view.DataContext;
viewModel.StringProperty = "blah";
// Now get a reference to the region in your View which will host
// the "child" views.
var regionManager = container.Resolve<IRegionManager>();
var region = regionManager.Regions["MyRegionName"];
// Finally add the view to the region. You can do it manually, you
// can use the concept of "navigation" if your MVVM framework has one
// (I 'm using Prism, which does), etc etc.
region.Add(view);
}
更新:在撰写答案时,我忘记并非所有MVVM框架都像棱镜一样具有区域。所以请原谅上面代码的特殊性,因为它并没有真正改变任何东西。你只需要自己构建像Region抽象这样的东西。我们来看看:
class MyViewModel {
public event EventHandler<ChildViewModelAddedEventArgs> ChildViewModelAdded;
}
然后 MyView
会将事件处理程序附加到此事件,然后从ChildView
内部选择ChildViewModelAddedEventArgs
实例,以便将其添加到ItemsControl
它是没有你的ViewModel的父母搞乱这些细节。
当然这意味着您现在需要一些代码隐藏,但除非您使用自己提供此类服务的框架,否则无法提供帮助。