Prism MVVM - Add child View to parent View without using Regions and Injection, just XAML
I'm fairly new to the Silverlight and the MVVM / Prism pattern so this may be a stupid question.
I have a View which has custom controls within it. These custom controls are actually Views too and have ViewModels to drive them.
Currently to add these 'child' Views to the View I'm using (see Fig.1) and then in the ViewModel I have an Initialise() method which resolves the child View and injects it (see Fig.2).
Fig.1
<UserControl
x:Class="ProjectA.Module.Screens.Views.PlatformScreenView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Regions="clr-namespace:Microsoft.Practices.Composite.Presentation.Regions;assembly=Microsoft.Practices.Composite.Presentation"
>
<Grid x:Name="LayoutRoot">
<ContentControl
Regions:RegionManager.RegionName="FeaturesSelectionControl"
/>
</Grid>
Fig.2
public void Initialise()
{
IRegion featuresRegion = _regionManager.Regions["FeaturesSelectionControl"];
featuresRegion.Add(_container.Resolve<IFeatureSelectionControlViewModel>().View);
}
My question is do I have to do this for every control I want to add? I understand why it works this way but it seems like quite a bit of code and also I need to keep track of all the region names and ensure I don't have any clashes etc. Is there a simpler way of doing this without regions and just in XAML?
I've seen a snippet of XAML on S开发者_运维问答tackOverflow here but not sure how it works and if it's what I want -
<ContentControl Content="{Binding SmartFormViewModel}"/>
Any help is much appreciated.
James
Edit after clarification:
It appears you don't want to use RegionManager at all, which is fine. What I would suggest then is this:
Create an interface for your Modules to use to register view creation methods:
public interface IViewRegistry
{
void RegisterMainView(Func<object> ViewCreationDelegate);
}
Your modules will use this like this:
public MyModule : IModule
{
IViewRegistry _registry;
public MyModule(IViewRegistry registry)
{
_registry = registry;
}
public void Initialize()
{
_registry.RegisterMainView(() =>
{
var vm = new MyViewModel();
var view = new MyView();
var view.DataContext = vm;
return view;
});
}
}
Then in your shell, you first implement the view registry (this is a simplification... you'd probably want something more robust)
public ViewRegistry : IViewRegistry
{
public static List<Func<object>> ViewFactories
{
get { return _viewFactories; }
}
static List<Func<object>> _viewFactories = new List<Func<object>>();
public void RegisterMainView(Func<object> viewFactory)
{
_viewFactories.Add(viewFactory);
}
}
And lastly, here's how your shell would show that stuff. Here's its ViewModel first:
public ShellViewModel : ViewModel
{
public ObservableCollection<object> MainViews
{
...
}
public ShellViewModel()
{
MainViews = new ObservableCollection<object>(ViewRegistry.Select(factory => factory()));
}
}
And here's your View (look ma, no RegionManager!):
<UserControl ...>
<Grid>
<ItemsControl ItemsSource="{Binding MainViews}" />
</Grid>
</UserControl>
The region manager sort of attempts to give you everything I've written here, plus a lot of extensibility points, but if you don't like RegionManager or you find it doesn't fit your needs for some reason, this is how you would do this in Silverlight without it.
Further Edits:
After some more commentary from the OP, I think I understand that the OP just wants to show a view within another view without having to use RegionManager. It appears the OP is using RegionManager to show every view on the screen, which is probably overkill.
The scenario I was given included an Address View and associated ViewModel being used from a different parent control. This is what I do (whether right or wrong):
<UserControl x:Class="Views.MyParentView" ...>
<StackPanel>
<TextBlock>Blah blah blah some other stuff... blah blah</TextBlock>
<myViews:AddressView DataContext="{Binding AddressVM}" />
</StackPanel>
</UserControl>
And here's the parent view's viewModel:
public ParentViewModel : ViewModel
{
public AddressViewModel AddressVM
{
...
}
public ParentViewModel()
{
AddressVM = new AddressViewModel();
}
}
That's it. This prevents you from having to work too hard to show these views.
RegionManager is really appropriate for decoupling the parent container view from the subview, but if both of these live in the same place (same module / assembly) there is no reason to use RegionManager to show these views.
精彩评论