Reputation: 1336
I have a WPF Window containing a TabControl, which has Frames in it which display Pages. Like this:
<Window x:Class="MyNamespace.View.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow">
<DockPanel>
<TabControl x:Name="TabControl">
<TabItem Header="StartScreen" x:Name="StartScreenTab">
<Frame Source="StartScreenPage.xaml"/>
</TabItem>
<TabItem Header="OtherTab" x:Name="OtherTab">
<Frame Source="OtherPage.xaml"/>
</TabItem>
</TabControl>
</DockPanel>
</Window>
In one of the pages, I have a KeyBinding:
<Page x:Class="MyNamespace.View.OtherPage"
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"
Title="OtherPage">
<Page.InputBindings>
<KeyBinding Key="U" Modifiers="Control" Command="{Binding MyCommand}"/>
</Page.InputBindings>
<!-- Content ... -->
</Page>
MyCommand
is a property of OtherPage.DataContext
, it's only available from the page, not available from outside.
My problem is that the KeyBinding only works after I click on a control inside the Page. I want that KeyBinding to work whenever OtherPage
is visible, equivalently when OtherTab
is the active tab. How can I achieve this?
Upvotes: 2
Views: 2212
Reputation: 1336
I did something similar to what Sheridan recommended in his answer.
In MainWindow.xaml
I declare a RoutedUICommand
:
<Window x:Class="MyNamespace.View.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow">
<Window.Resources>
<ResourceDictionary>
<RoutedUICommand x:Key="OtherPageCommand"/>
</ResourceDictionary>
</Window.Resources>
<Window.CommandBindings>
<CommandBinding Command="{StaticResource OtherPageCommand}"
Executed="OtherPageCommandExecuted"/>
</Window.CommandBindings>
<Window.InputBindings>
<KeyBinding Key="U" Modifiers="Control" Command="{StaticResource OtherPageCommand}"/>
</Window.InputBindings>
<DockPanel>
<TabControl x:Name="TabControl">
<TabItem Header="StartScreen" x:Name="StartScreenTab">
<Frame Source="StartScreenPage.xaml"/>
</TabItem>
<TabItem Header="OtherTab" x:Name="OtherTab">
<Frame Source="OtherPage.xaml"/>
</TabItem>
</TabControl>
</DockPanel>
</Window>
In MainWindow.xaml.cs
I have this method:
private void OtherPageCommandExecuted(object sender, ExecutedRoutedEventArgs e)
{
var page = ((Frame)((TabItem) TabControl.SelectedItem).Content).Content as OtherPage;
if (page != null)
{
var viewModel = page.DataContext as MyViewModel;
if (viewModel != null)
{
var openWindow = viewModel.MyCommand;
var parameter = null; // put your command parameter here
if (openWindow.CanExecute(parameter))
openWindow.Execute(parameter);
}
}
}
This way I propagate the keybinding to the page but the actual command remains in the viewmodel of the page.
Upvotes: 1
Reputation: 69959
The only way that you can achieve that is to move your KeyBinding
and the ICommand
implementation to the MainWindow.xaml
file:
<Window.InputBindings>
<KeyBinding Key="U" Modifiers="Control" Command="{Binding MyCommand}"/>
</Window.InputBindings>
If you can't move the actual implementation of the ICommand
, then you must at least make it accessible from there.
Upvotes: 1