Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
679 views
in Technique[技术] by (71.8m points)

wpf - XAML - How to have global inputBindings?

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!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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!"); }
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...