MVVM和控件创建

时间:2011-03-04 18:34:07

标签: c# wpf mvvm wpf-controls

想象一个简单的场景,WPF窗口包含一个按钮和一些空白区域。单击该按钮可创建一个新的自定义/用户控件,并将其随机放置在窗口上。

单击其中一个控件将其从窗口中删除。

所以现在我有了一个ViewModel ala MVVM,它为“创建新”按钮公开了一个ICommand,但创建新控件的代码在哪里生效?每个控件可能都有自己的ViewModel,它可以处理它的删除和定位。

可以在窗口上没有代码的情况下实现它并且ViewModel对View没有真正的了解吗?

2 个答案:

答案 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的父母搞乱这些细节。

当然这意味着您现在需要一些代码隐藏,但除非您使用自己提供此类服务的框架,否则无法提供帮助。