In deze post ga ik het hebben over een probleem waar ik tegen aan
ben gelopen bij het gebruik van Prism. Deze techniek wordt
toegepast in Silverlight -waarin wij werken- maar ook in WPF
applicaties. Deze techniek zorgt er voor dat de verschillende delen
van de applicatie losgekoppeld worden en daarmee makkelijk te
veranderen of te hergebruiken zijn. Voor meer informatie over Prism
ga naar http://compositewpf.codeplex.com/
of volg de goede tutorial van Channel9 hier:
http://channel9.msdn.com/posts/akMSFT/Creating-a-modular-application-using-Prism-V2-Part-1-of-4--Creating-a-shell-and-modules/.
Het probleem
Wanneer ik in Prism verschillende Regions defineer en
daar views in stop, kan ik niet de lay-out van mijn applicatie
drastisch veranderen per scherm. Neem bijvoorbeeld deze
lay-out:

Wat als ik nou een loginscherm wil hebben waarbij bijvoorbeeld
linksboven het login gedeelte zit en in het midden een news feed?
Dan moeten mijn regions wel heel anders gedefinieerd zijn dan
hierboven het geval is. Na een tijdje hiermee gestoeid te hebben
ben ik tot de volgende oplossing gekomen.
De oplossing
Eerst heb ik een full screen region gemaakt in de shell.xaml.
Dit is de enige region in de Shell.
<ContentControl regions:RegionManager.RegionName="FullScreen"
VerticalContentAlignment="Stretch"
HorizontalContentAlignment="Stretch">
</ContentControl>
Wanneer de applicatie opstart registreer ik de Welcome view met
het fullscreen region:
m_regionManager.RegisterViewWithRegion(Regions.FullScreen.ToString(), () =>
m_container.Resolve<ViewWelcome>());
De ViewWelcome heeft zijn eigen regions voor het login scherm,
zoals ik boven beschreven heb.
Wanneer de gebruiker is ingelogd, deactiveer ik het Welcome
scherm en activeer ik het Main scherm, deze bevat alle andere
regions zoals boven in het plaatje te zien is. Ik doe dit in de
Shell.xaml.cs codebehind, door me te subscriben aan een event door
gebruik te maken van de eventaggregator zoals hier in de
constructor:
m_regionManager.RegisterViewWithRegion(Regions.FullScreen.ToString(), () =>
m_container.Resolve<ViewWelcome>());
En dit is de method die gebruikt wordt om tussen de views te
wisselen:
private void switchViewsEventHandler(string viewSetName)
{
switch (viewSetName.ToLower())
{
case "login":
RegionViewManager.DeactivateView(
m_regionManager.Regions[Regions.FullScreen.ToString()],
typeof(ViewMain));
RegionViewManager.AddAndActivateView(
m_regionManager.Regions[Regions.FullScreen.ToString()],
typeof(ViewWelcome), m_container);
break;
case "main":
RegionViewManager.DeactivateView(
m_regionManager.Regions[Regions.FullScreen.ToString()],
typeof(ViewWelcome));
RegionViewManager.AddAndActivateView(
m_regionManager.Regions[Regions.FullScreen.ToString()],
typeof(ViewMain), m_container);
break;
}
}
Wat hier het interessante is, is waarschijnlijk de deactiveer en
activeer methods in de RegionViewManager class, dus die laat ik
hier zien.
public static class RegionViewManager
{
public static void DeactivateView(IRegion region, Type viewType)
{
foreach (object view in region.Views)
{
if (view.GetType() == viewType)
{
region.Deactivate(view);
}
}
}
public static void AddAndActivateView(IRegion region, Type viewType,
IUnityContainer container)
{
bool found = false;
foreach (var existingView in region.Views)
{
if(existingView.GetType() == viewType)
{
region.Activate(existingView);
found = true;
break;
}
}
if (!found)
{
var view = container.Resolve(viewType);
region.Add(view);
region.Activate(view);
}
}
}
Om het samen te vatten: eerst activeer ik de Welcome view, die
in de fullscreen region zit. Dan, wanneer ik inlog, deactiveer ik
de Welcome view en activeer ik de main view, die ook in de
Fullscreen region zit. Deze views hebben beide hun eigen regions.
Dit maakt het mogelijk om zoveel verschillende layouts voor mijn
applicatie te gebruiken als ik wil.
We zijn nog steeds bezig deze technieken te verbeteren. Als je
tips hebt, twijfel dan niet te reageren.