Region Navigation to jeden z rodzajów View Navigation. Mówiąc najprościej jest to podmiana widoku aktualnie wyświetlanego w danym regionie na inny widok.
W Prism mamy do dyspozycji bardzo prostą metodę RequestNavigate. Można ją wywołać na dwa sposoby:
- za pośrednictwem klasy Region:
Code:
IRegion myRegion = region;
myRegion.RequestNavigate("Name_of_view");
Metoda w tym przypadku przyjmuje tylko nazwę widoku który ma zostać wyświetlony w regionie.
- za pośrednictwem klasy IRegionManager:
Code:
IRegionManager regionManager = rm;
region.Manager.RequestNavigate(RegionNames.Content, new Uri("View", UriKind.Relative));
W tym przypadku podajemy region w którym ma zostać wyświetlony widok jak i jego nazwę.
W tym przykładzie pokażę w jaki sposób skorzystać z drugiej wersji, czyli za pomocą RegionManagera - co wydaje mi się, daje większe możliwości i większą elastyczność.
Na początek struktura projektu który będziemy tworzyć:
Aplikacja będzie prezentowała się w następujący sposób:
Po kliknięciu w przycisk Moduł A zostanie wyświetlona zawartość modułu A, a w Module B Modułu B - prosta sprawa :).
Myślę że nie będę więcej wklejać kodu, który można znaleźć w poprzednich postach z cyklu Prism. Tak więc tylko najważniejsze części kodu oraz ich opis.
Główne okno aplikacji:
Code:
<Window x:Class="Sample_application_1.Shell"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:prism="clr-namespace:Microsoft.Practices.Prism.Regions;assembly=Microsoft.Practices.Prism"
xmlns:Core="clr-namespace:Core;assembly=Core" Title="Shell" Height="300" Width="300">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackPanel prism:RegionManager.RegionName="{x:Static Core:RegionNames.ToolbarRegion}"
Grid.Row="0" Orientation="Horizontal"/>
<ContentControl prism:RegionManager.RegionName="{x:Static Core:RegionNames.ContentRegion}"
Grid.Row="1"/>
</Grid>
</Window>
Tak więc dwa regiony: pierwszy będzie zawierać przyciski nawigacji, drugi treść naszych widoków.
Jako że potrzebujemy wspólnego mechanizmu nawigacji stworzymy w bibliotece Core klasę ApplicationCommands:
Code:
using Microsoft.Practices.Prism.Commands;
namespace Core
{
public class ApplicationCommands
{
public static CompositeCommand NavigationCommand = new CompositeCommand();
}
}
Wejdźmy do modułu A:
Code:
using Core;
using Microsoft.Practices.Prism.Modularity;
using Microsoft.Practices.Prism.Regions;
using Microsoft.Practices.Unity;
using ModuleA.Navigation;
namespace ModuleA
{
public class ModuleAModule : IModule
{
private readonly IRegionManager _regionManager;
private readonly IUnityContainer _container;
public ModuleAModule(IRegionManager regionManager, IUnityContainer container)
{
_regionManager = regionManager;
_container = container;
}
public void Initialize()
{
_regionManager.RegisterViewWithRegion(RegionNames.ToolbarRegion, typeof (ButtonModuleA));
_container.RegisterType<object, ModuleA>(typeof(ModuleA).FullName);
}
}
}
Ważniejsze aspekty tego co tutaj zostało wykonane:
- w konstruktorze wstrzykujemy sobie potrzebne serwisy - kontener oraz region manager
- standardowo za pomocą ViewDiscovery dodajemy nasz przycisk do Toolbara
- Najważniejsze: rejestrujemy nasz widok A w kontenerze jako reprezentację typu object. Jest to bardzo ważne i jeżeli chcemy skorzystać z dobrodziejstwa nawigacji musimy w ten sposób zarejestrować nasz widok.
Zobaczmy następnie jaki kod zawiera ViewModel:
Code:
using Core;
using Microsoft.Practices.Prism.Commands;
using Microsoft.Practices.Prism.Regions;
namespace ModuleA
{
public class ModuleAViewModel
{
}
}
Właściwie to nic nie ma tutaj ciekawego. Tak samo będzie wyglądać VM drugiego modułu.
Chcemy aby nasz model nawigacji nie był związany z konkretnym widokiem. Implementacja poruszania się po naszej aplikacji zostanie stworzona w VM Shell-a. Zobaczmy więc na kod który znajduje się w Shell-u:
Code:
using Core;
using Microsoft.Practices.Prism.Commands;
using Microsoft.Practices.Prism.Regions;
namespace Sample_application_1
{
public class ShellViewModel
{
private readonly IRegionManager _regionManager;
public DelegateCommand<object> NavigationCommand { get; private set; }
public ShellViewModel(IRegionManager regionManager)
{
_regionManager = regionManager;
NavigationCommand = new DelegateCommand<object>(navigationPath =>
{
if (navigationPath != null)
{
regionManager.RequestNavigate(RegionNames.ContentRegion, navigationPath.ToString());
}
});
ApplicationCommands.NavigationCommand.RegisterCommand(NavigationCommand);
}
}
}
Kolejno idąc tokiem kodu:
- tworzymy deklarację komendy NavigateCommand która ma za zadanie przenieść nas do odpowiedniego modułu
- W konstruktorze tworzymy ją i za pomocą RequestNavigate przenosimy się do odpowiedniego widoku.
- Jednym z parametrów metody jest navigationPath, która zostanie przysłana jako parametr komendy a decyduje ona o adresie widoku do którego chcemy się przenieść
- Rejestrujemy naszą komendę w CompositeCommand NavigationCommand
Widok przycisku Modułu A:
Code:
<UserControl x:Class="ModuleA.Navigation.ButtonModuleA"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
xmlns:Core="clr-namespace:Core;assembly=Core"
xmlns:ModuleA="clr-namespace:ModuleA">
<Grid>
<Button Content="Moduł A" Command="{x:Static Core:ApplicationCommands.NavigationCommand}"
CommandParameter="{x:Type ModuleA:ModuleA}"/>
</Grid>
</UserControl>
Bindujemy się do naszej komendy, a następnie jako parametr przekazujemy nazwę widoku, pobraną z enuma:
Code:
namespace ModuleA
{
public enum ViewType
{
ModuleA
}
}
Teraz możemy włączyć naszą aplikację i przemieszczać się pomiędzy widokami.
Brak komentarzy:
Prześlij komentarz