2009-07-09 15 views
6

Ich habe eine WPF-Anwendung mit mehreren Fenstern. Ich möchte GLOBAL inputBindings definieren.XAML - Wie globale InputBindings haben?

Um lokale Eingabebindungen zu definieren, deklariere ich einfach die Eingabe in Window.InputBindings oder UserControl.InputBindings.

Globals zu definieren, ich wünsche, dass ich mit der Application-Klasse das gleiche tun könnte ...

<Application 
....> 
<Application.InputBindings> 
... 
</Application.InputBindings> 

Wenn ich die gleiche Bindung in 2 verschiedenen Fenstern haben, ich habe es zweimal zu codieren. Dies entspricht nicht der Philosophie von D.R.Y. und ich denke, es gibt einen besseren Weg ...

EDIT: in seiner Antwort Kent Boogaart rät mir, Style zu verwenden. Leider kann ich nicht herausfinden, wie man es definiert. Dies ist der 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> 

Es löst einen Fehler aus: Fehler MC3080: Die ‚Inputbindings‘ Property Setter kann nicht eingestellt werden, weil es keine zugängliche Set Accessor hat.

Ist mein Stil falsch? Gibt es eine andere Lösung?

Irgendwelche Ideen? Vielen Dank!

Antwort

9

Eine Lösung besteht darin, einen Attached Property mit einem Style zu verwenden, um den InputBindings für alle Steuerelemente eines bestimmten Typs in Ihrer Anwendung festzulegen. Leider, da Sie kein "Catch-all" Style (das ich weiß, auf jeden Fall), müssen Sie ein Style für jeden Steuerelementtyp erstellen, auf dem Sie die InputBindings setzen möchten (das sollte nicht, jedoch zu viele Kontrollen). Nachfolgend finden Sie einige Beispielcode, der zeigt, wie dies zu tun:

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

Vorsicht - ich einige sehr seltsame Probleme hatte, als den obigen Code verwenden. Es funktionierte großartig, bis ich es auf einen Stil anwandte, dann schien es in zufälligen Fällen zu funktionieren, aber dann wäre der DataContext null (also würde keiner der Befehle binden). Ich konnte nicht herausfinden, warum das zufällig passieren würde. – Asheh

0

Sie könnten eine Style erstellen, die auf alle Ihre Window s angewendet wird. Das Style könnte die InputBindings setzen.