XAML - How to have global inputBindings?
inputbinding, wpf, xaml
Solution
One solution is to use an Attached Property with a `Style` to set the `InputBindings` on all the controls of a given type in your application. Unfortunately, since you can't make a "catch-all" `Style` (that I know of, anyway), you'll have to create a `Style` for each control type on which you want to set the `InputBindings` (this shouldn't, however, be too many controls). Below is some sample code that shows how to do this:
using System.Windows;
using System.Windows.Input;
namespace WpfApplication1
{
public class MyAttached
{
public static readonly DependencyProperty InputBindingsProperty =
DependencyProperty.RegisterAttached("InputBindings", typeof(InputBindingCollection), typeof(MyAttached),
new FrameworkPropertyMetadata(new InputBindingCollection(),
(sender, e) =>
{
var element = sender as UIElement;
if (element == null) return;
element.InputBindings.Clear();
element.InputBindings.AddRange((InputBindingCollection)e.NewValue);
}));
public static InputBindingCollection GetInputBindings(UIElement element)
{
return (InputBindingCollection)element.GetValue(InputBindingsProperty);
}
public static void SetInputBindings(UIElement element, InputBindingCollection inputBindings)
{
element.SetValue(InputBindingsProperty, inputBindings);
}
}
}
<Application x:Class="WpfApplication1.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:loc="clr-namespace:WpfApplication1"
StartupUri="Window1.xaml">
<Application.Resources>
<Style TargetType="TextBox">
<Setter Property="loc:MyAttached.InputBindings">
<Setter.Value>
<InputBindingCollection>
<KeyBinding Key="A" Modifiers="Ctrl" Command="loc:Window1.MyAction" />
</InputBindingCollection>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="Button">
<Setter Property="loc:MyAttached.InputBindings">
<Setter.Value>
<InputBindingCollection>
<KeyBinding Key="A" Modifiers="Ctrl" Command="loc:Window1.MyAction" />
</InputBindingCollection>
</Setter.Value>
</Setter>
</Style>
</Application.Resources>
</Application>
<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:loc="clr-namespace:WpfApplication1"
Title="Window1" Height="300" Width="300">
<Window.CommandBindings>
<CommandBinding Command="loc:Window1.MyAction" Executed="MyAction_Executed" />
</Window.CommandBindings>
<StackPanel>
<Button Content="Try Ctrl+A Here!" />
<TextBox Text="Try Ctrl+A Here!" />
</StackPanel>
</Window>
using System.Windows;
using System.Windows.Input;
namespace WpfApplication1
{
public partial class Window1
{
public static readonly RoutedUICommand MyAction = new RoutedUICommand("MyAction", "MyAction", typeof(Window1));
public Window1() { InitializeComponent(); }
private void MyAction_Executed(object sender, ExecutedRoutedEventArgs e) { MessageBox.Show("MyAction!"); }
}
}
Problem
I have a WPF application with several windows. I would like to define GLOBAL inputBindings. To define LOCAL inputbindings, i just declare the input in Window.InputBindings or UserControl.InputBindings. To define GLOBALs, I wish i could do the same with the Application class... ``` <Application ....> <Application.InputBindings> ... </Application.InputBindings> ``` If i have the same binding in 2 different windows, i have to code it twice. This doesn't meet D.R.Y.'s philosophy and i guess there is a better way... EDIT : in his answer Kent Boogaart advices me to use Style. Unfortunately, i can't figure out how to define it. This is the code : ``` <Application.Resources> <Style TargetType="Window"> <Setter Property="InputBindings"> <Setter.Value> <Window.InputBindings> <KeyBinding KeyGesture="Ctrl+M" Command="local:App.MsgCommand /> </Window.InputBindings> </Setter.Value> </Setter> </Style> </Application.Resources> ``` It raises an error : error MC3080: The Property Setter 'InputBindings' cannot be set because it does not have an accessible set accessor. Is my style wrong? Is there another solution? Any ideas? thanks!