Reputation: 3
I have a ControlTemplate
for a Menu which I want to be used for all my Pages. The function calls of the ControlTemplate
requires the usage of the NavigationService
belonging my NavigationWindow
. However, I can not place the ControlTemplate
in the NavigationWindow xaml
file, because it is not accessible to the Pages. How would I allow my ControlTemplate
to access the NavigationService
while being available to use in my Pages?
My NavigationWindow
is located at MainWindow.xaml
App.xaml.cs
namespace WPFApplication
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
private void Menu_ModeAdvanced_Click(object sender, RoutedEventArgs e)
{
// Where I want to access the Navigation Service
}
}
}
App.xaml
<Application x:Class="WPFApplication.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WPFApplication"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<!-- Page Design -->
<Style TargetType="Page">
<Setter Property="Foreground" Value="#FBF5F3" />
<Setter Property="Background" Value="#363537" />
</Style>
<!-- Label Design-->
<Style TargetType="Label">
<Setter Property="Foreground" Value="#FBF5F3" />
</Style>
</ResourceDictionary>
<!-- Menu Template-->
<ControlTemplate x:Key="StandardMenu" TargetType="Menu">
<Menu Height="20">
<MenuItem Header="File" AllowDrop="True">
<MenuItem Header="Mode" AllowDrop="True">
<MenuItem Header="Advanced"/>
</MenuItem>
</MenuItem>
</Menu>
</ControlTemplate>
</Application.Resources>
</Application>
I have tried putting the ControlTemplate
and related code into a ResourceDictionary
located in the NavigationWindow
's class. However, I could not use it as a static resource in my pages.
Upvotes: -1
Views: 54
Reputation: 28948
Simply get the parent Window
of the MenuItem
. If it is the NavigationWindow
you can use its API to execute navigation related tasks or use its associated NavigationWindow.NavigationService
:
private void Menu_ModeAdvanced_Click(object sender, RoutedEventArgs e)
{
FrameworkElement element = sender as FramwworkElement;
NavigationWindow navigationWindow = null;
while (element.Parent is not null)
{
element = element.Parent as FrameworkElement;
if (element is NavigationWindow window)
{
navigationWindow = window;
break;
}
}
// Navigate etc. using the NavigationWindow API
navigationWindow?.Navigate(new Uri());
// Navigate etc. using the NavigationService
navigationWindow?.NavigationService.Navigate(new Uri());
}
But I recommend defining routed commands in your NavigationWindow
.
It's much cleaner from a design perspective as the navigation details are kept private to the navigation host:
MainWindow.xaml.cs
partial class MainWindow : NavigationWindow
{
public static RoutedCommand NavigateToPageCommand { get; }
= new RoutedCommand(nameof(MainWindow.NavigateToPageCommand, typeof(MainWindow));
private Dictionary<PageId, Uri> PageUriStore { get; }
public MainWindow()
{
InitializeComponent();
var navigateCommandBinding = new CommandBinding(
MainWindow.NavigateToPageCommand,
ExecutedNavigateToPageCommand,
CanexecutedNavigateToPageCommand);
this.CommandBindings.Add(navigateCommandBinding);
this.PageUriStore = new Dictionary<PageId, Uri>
{
{ PageId.SettingsPage, new Uri(...) },
};
}
private void CanexecutedNavigateToPageCommand(object sender, ExecutedRoutedEventArgs e)
=> e.CanExecute = e.Parameter is PageId;
private void CanexecutedNavigateToPageCommand(object sender, ExecutedRoutedEventArgs e)
{
var pageId = (PageId)e.Parameter;
if (this.PageUriStore.TryGetValue(pageId, out Uri destinationUri))
{
this.Navigate(ddestinationUri);
}
}
}
App.xaml
<MenuItem Header="Settings"
Command="{x:Static MainWindow.NavigateToPageCommand}"
CommandParameter="{x:Static PageId.SettingsPage}" />
PageId.cs
enum PageId
{
Default = 0,
OverviewPage,
SettingsPage
}
Upvotes: 0