This article has the goal to show how to create a blank window in WPF using Modern UI, which handle the navigation.
Modern UI is a set of controls and styles converting our WPF application into a great looking Modern UI app. The Modern UI project can be found in mui.codeplex.com, here it is possible to get the WPF app that demonstrates the features provided by "mui".
WPF don´t have a pattern for the navigation when we are using Windows, only exist a navigation service when we use Pages. ModernUI introduce a special way for the navigation, that use the ModernFrame.
The question here is, how I know when the user is navigating from one view to another?
In the sample Modern UI for WPF application by example (Default Window) we saw the default window provided by Modern UI, and in this sample we will use the same base code but we will change the code for handle the navigation.
If we search the properties from the ModernWindow, we will see that it don´t have any event or method for handle navigation. After some search in documentation, we find an article Handle navigation events in your content.
Let's apply it!
The MainWindow contains a MenuLinkGroups which contains a LinkGroup with two Links. Each link is defined by a UserControl. For handle navigation, each user control will implement the interface IContent, like following
/// <
summary
>
/// Interaction logic for StepsControl.xaml.
/// </
public partial class StepsControl : IContent
{
/// Initializes a new instance of the <
see
cref
=
"StepsControl"
/> class.
public StepsControl()
InitializeComponent();
}
/// Called when navigation to a content fragment begins.
param
name
"e"
>An object that contains the navigation data.</
public void OnFragmentNavigation(FragmentNavigationEventArgs e)
Debug.WriteLine("StepsControl- OnFragmentNavigation");
/// Called when this instance is no longer the active content in a frame.
public void OnNavigatedFrom(NavigationEventArgs e)
Debug.WriteLine("StepsControl -OnNavigatedFrom");
/// Called when a this instance becomes the active content in a frame.
public void OnNavigatedTo(NavigationEventArgs e)
Debug.WriteLine("StepsControl- OnNavigatedTo");
/// Called just before this instance is no longer the active content in a frame.
/// An object that contains the navigation data.
remarks
/// The method is also invoked when parent frames are about to navigate.
public void OnNavigatingFrom(NavigatingCancelEventArgs e)
Debug.WriteLine("StepsControl- OnNavigatingFrom");
Using Debug.WriteLine we will show in output window the flow when we navigate in MainWindow.
The output will be something like
StepsControl - OnNavigatedTo
StepsControl - OnNavigatingFrom
StepsControl - OnNavigatedFrom
ResourcesControl - OnNavigatedTo
ResourcesControl - OnNavigatingFrom
ResourcesControl - OnNavigatedFrom
See the code source in github - ModernUIForWPFSample.Navigation (Default) .
Suppose when we navigate we want to do some task and we are using the MVVM pattern. We could get the view model defined in DataContext and then call method that apply what we want, something like
var viewModel = DataContext as MyViewModel;
if (viewModel != null)
viewModel.DoSomething();
or we can define events that will be called when the methods from IContent are raised and this events can be defined in UI using the EventTrigger and InvokeCommandAction. With this we will avoid code in code behiden.
First we will create our ModernUserControl which is a UserControl and implements the IContent. This control will have four events, one for each method required for IContent.
The implementation will be something like
public class ModernUserControl : UserControl, IContent
/// Handles the <
"E:FragmentNavigation"
/> event.
>The <
"FirstFloor.ModernUI.Windows.Navigation.FragmentNavigationEventArgs"
/> instance containing the event data.</
if (FragmentNavigation != null)
FragmentNavigation(this, e);
"E:NavigatedFrom"
"FirstFloor.ModernUI.Windows.Navigation.NavigationEventArgs"
if (NavigatedFrom != null)
NavigatedFrom(this, e);
"E:NavigatedTo"
if (NavigatedTo != null)
NavigatedTo(this, e);
"E:NavigatingFrom"
"FirstFloor.ModernUI.Windows.Navigation.NavigatingCancelEventArgs"
if (NavigatingFrom != null)
NavigatingFrom(this, e);
/// Occurs when [navigating from].
public event NavigatingCancelHandler NavigatingFrom;
/// Occurs when [navigated from].
public event NavigationEventHandler NavigatedFrom;
/// Occurs when [navigated to].
public event NavigationEventHandler NavigatedTo;
/// Occurs when [fragment navigation].
public event FragmentNavigationHandler FragmentNavigation;
<
controls:ModernUserControl
x:Class
"ModernUIForWPFSample.Navigation.Views.StepsControl"
xmlns
"http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x
"http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d
"http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc
"http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:controls
"clr-namespace:ModernUIForWPFSample.Navigation__MVVM_.Controls"
xmlns:i
"http://schemas.microsoft.com/expression/2010/interactivity"
d:DesignHeight
"300"
d:DesignWidth
"600"
mc:Ignorable
"d"
DataContext
"{Binding StepsViewModel, Source={StaticResource Locator}}"
i:Interaction.Triggers
i:EventTrigger
EventName
"NavigatedTo"
i:InvokeCommandAction
Command
"{Binding NavigatedToCommand}"
/>
</
"NavigatedFrom"
"{Binding NavigatedFromCommand}"
"NavigatingFrom"
"{Binding NavigatingFromCommand}"
"FragmentNavigation"
"{Binding FragmentNavigationCommand}"
"Loaded"
"{Binding LoadedCommand}"
"IsVisibleChanged"
"{Binding IsVisibleChangedCommand}"
Grid
TextBlock
HorizontalAlignment
"Center"
VerticalAlignment
TextWrapping
"Wrap"
Steps:
LineBreak
1st Install the ModernUI from Nuget
2nd Define in App.xaml the resources for ModernUI.xaml and ModernUI.Light.xaml
3rd Change the MainWindow: Replace the tag "Window" to ModernWindow
4th Define the content for the MainWindow using TitleLinks, MenuLinkGroups, LinkGroup...
5th Define which content is shown when the application start, by using the ContentSource
6th For each content (in this case for StepsControl and ResourcesControl) must implement the interface IContent
7th For each navigation method (OnFragmentNavigation, OnNavigatedFrom, OnNavigatedTo and OnNavigatingFrom) add the behavior you want
Note: For change the appearance use AppearanceManager class
For help in th MVVM pattern implementation we will use MVVMLight Toolkit and we will have two view models (StepsViewModel and ResourcesViewModel). Here are the class diagram.
ViewModelLocator will help in binding the view model to the view and is where we setup the dependencies when we use dependency injection.
When we ran the application the output will be something like
ModernUserControl - OnNavigatedTo
StepsViewModel - LoadData
ModernUserControl - OnNavigatingFrom
StepsViewModel - NavigatingFrom
ModernUserControl - OnNavigatingFrom event called
ModernUserControl - OnNavigatedFrom
StepsViewModel - NavigatedFrom
ModernUserControl - OnNavigatedFrom event called
ResourcesViewModel - LoadData
ResourcesViewModel - NavigatingFrom
ResourcesViewModel - NavigatedFrom
StepsViewModel - NavigatedTo
ModernUserControl - OnNavigatedTo event called
With it, we can conclude when we use events, the NavigateTo event is not raised at the first time the control is shown, it because the NavigateTo event wasn´t subscribed when the first navigation occurs.
See others solutions for Navigation in ModernUI applications.
Modern UI for WPF application by example ( NavigationMessageService - MVVM )
Modern UI for WPF application by example ( NavigationService - MVVM )
Get the source code for this sample in github.