Reputation: 4909
Imagine a simple scenario with a WPF window containing a button and some clear space. Clicking the button creates a new custom/user control and places it somewhere randomly on the window.
Clicking one of these controls will remove it from the window.
So now I have a ViewModel ala MVVM which exposes an ICommand for the "create new" button, but where does the code to create the new control live? Each control will probably have its own ViewModel which will handle its deletion and positioning I guess.
Can it be achieved with no code behind on the window AND no real knowledge of the View by the ViewModel?
Upvotes: 2
Views: 315
Reputation: 437336
The code that causes the controls to be created lives inside your "main" ViewModel.
The code that actually creates the controls is the container.
So it would go something like:
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);
}
Update: When writing the answer, I forgot that not all MVVM frameworks have Regions as Prism does. So excuse the specificity of the code above, as it doesn't really change anything. You simply need to build something like the Region abstraction yourself. Let's see:
class MyViewModel {
public event EventHandler<ChildViewModelAddedEventArgs> ChildViewModelAdded;
}
MyView
would then attach an event handler to this event, and pick up the ChildView
instance from inside ChildViewModelAddedEventArgs
so that it can be added to an ItemsControl
it is the parent of without your ViewModel messing with such details.
Of course this means that you now need some code-behind, but this cannot be helped unless you are using a framework that provides such services itself.
Upvotes: 1
Reputation: 6675
This SHOULD be doable with some very careful databinding on an ItemsControl, not sure how you would achieve the layout, but you will have a parent view model containing a collection of child view models, layout would then be preformed by the ItemsControl. When the parent ViewModel created the child ViewModel, it should inject a RelayCommand as a lambda expression to remove and cleanup the child ViewModel from the parents collection.
Upvotes: 1