wtorek, 29 listopada 2011

Prism cz. 3 - Regiony

Regiony są podstawą aplikacji napisanych za pomocą Prism'a. Ułatwiają nawigację po programie i pozwalają na dynamiczną lokację widoków w naszej aplikacji. Regiony dzielą graficzny interfejs użytkownika na obszary, do których wczytywane są odpowiednie widoki. Wystarczy w kodzie wpisać że do Regionu A trzeba załadować Widok B. Prosty podział standardowej aplikacji na regiony może wyglądać tak:

W xaml'u wyglądałoby to mniej więcej w ten sposób:
<Grid ...>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="4*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="4*"/>
</Grid.RowDefinitions>
<ContentControl Regions:RegionManager.RegionName="LogoRegion" Grid.ColumnSpan="2"/>
<ContentControl Regions:RegionManager.RegionName="NavigatorRegion" Grid.Row="1"/>
<ContentControl Regions:RegionManager.RegionName="MainRegion" Grid.Column="1" Grid.Row="1"/>
</Grid>

Tak jak widać powyżej regiony definiujemy poprzez AttachedProperty RegionName klasy RegionManager. Od tej pory jeżeli w kodzie wywołamy następującą metodę:
regionManager.Regions["MainRegion"].Activate(view);

w obszarze "MainRegion" pojawi się nasz widok. Oznacza to tyle samo, że właściwość Content naszej ContentControl zostanie wypełniona obiektem "view". Oczywiście regiony mogą być zagnieżdżone jeden w drugim i Prism bez problemu poradzi sobie z taką sytuacją.

Powyższe rozwiązanie aktywacji widoku powinno być opakowane w jakiś obiekt pośredni. Nie zawsze bowiem mamy dostęp do obiektu widoku, w momencie gdy chcemy go aktywować. Naturalny wydaje się poniższy zapis:
ViewService.ActivateView(Type type);
ViewService.ActivateView(string viewName);

W pierwszym zapisie tak czy inaczej musimy mieć dostęp do typu widoku. Drugie rozwiązanie wydaje się bardziej elastyczne. Możemy je zaimplementować bez konieczności dołączania referencji do projektu z interfejsem graficznym. Przykładowy kod może wyglądać tak:
public void ActivateView(string viewName)
{
foreach (IRegion region in regionManager.Regions)
{
object view;
if (RegionContainsViewName(region, viewName, out view))
{
region.Activate(view);
break;
}
}
}

Na koniec mała wskazówka jeżeli chodzi o utrzymanie kodu. Nasz kod może być trudny w utrzymaniu, jeżeli np. chcemy zmienić nazwę regionu dlatego dobrą praktyką jest trzymanie nazw jako stałych. Jest to bardzo proste do rozwiązania w WPF'ie, gdzie możemy się odwoływać do stałych poprzez x:Static. Jeżeli chodzi o Silverlight warto zastosować pewne obejście:
<Grid.Resources>
<ResourceDictionary>
<Resources:Names x:Key="Names"/>
</ResourceDictionary>
</Grid.Resources>
...
<ContentControl Regions:RegionManager.RegionName="{Binding NavigatorRegion, Source={StaticResource Names}}"/>
<ContentControl Regions:RegionManager.RegionName="{Binding MainRegion, Source={StaticResource Names}}"/>

gdzie klasa Names może wyglądać następująco:
public class Names
{
public string MainRegion { get { return "MainRegion"; } }
public string NavigatorRegion { get { return "NavigatorRegion"; } }
}

0 komentarze:

Prześlij komentarz

 
Design by Free WordPress Themes | Bloggerized by Lasantha - Premium Blogger Themes | Online Project management