2016-10-12 4 views
2

私のアプリケーションにいくつかの一般的なキーボードショートカットを追加したいと思います。現在、すべてのビューXAMLで、私はこのコードを追加します。コードの後ろにコードをバインドするコマンドをバインドする

<Window.InputBindings> 
    <KeyBinding Command="{Binding ZoomInCommand}" Key="Add" Modifiers="Control" /> 
    <KeyBinding Command="{Binding ZoomOutCommand}" Key="Subtract" Modifiers="Control" /> 
</Window.InputBindings> 

は、私はこれを一般化するため、私は、WPFウィンドウクラスをサブクラス化し、代わりに新しく作成されたサブクラスを使用します。今、私はどのようにこれらのキーボードコマンドを対応するコードにバインドできるのだろうかと思っています。

public class MyWindow : Window 
{ 
    public MyWindow() 
    { 
     DataContextChanged += OnDataContextChanged; 
    } 

    private void OnDataContextChanged(object sender, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs) 
    { 
     InputBindings.Clear(); 
     var dataContext = DataContext as IZoomableViewModel; 
     if (dataContext != null) 
     { 
      InputBindings.Add(new KeyBinding(dataContext.ZoomInCommand, Key.Add, ModifierKeys.Control)); 
      InputBindings.Add(new KeyBinding(dataContext.ZoomOutCommand, Key.Subtract, ModifierKeys.Control)); 
     } 
    } 
} 

をしかし、私は直接のDataContextへのアクセス権を持っているとバインディング()オブジェクトを使用するのではなく、それをキャストする必要があるとして、これは、私には右見ていない:現在、それはこのようになります。 MVVMのように見えるようにコードを変更するにはどうすればよいですか?

答えて

1

必要なものはです。依存関係のプロパティMyWindow

、あなたのコマンドの両方ためICommand依存関係プロパティを作成し、あなたもとき、依存関係プロパティ値の変更をコールバックメソッドを実装する必要があります、ここでZoomInCommandための一つだ:

public ICommand ZoomInCommand 
{ 
    get { return (ICommand)GetValue(ZoomInCommandProperty); } 
    set { SetValue(ZoomInCommandProperty, value); } 
} 

// Using a DependencyProperty as the backing store for ZoomInCommand. This enables animation, styling, binding, etc... 
public static readonly DependencyProperty ZoomInCommandProperty = 
    DependencyProperty.Register("ZoomInCommand", typeof(ICommand), typeof(MyWindow), new PropertyMetadata(null, new PropertyChangedCallback(OnZoomInCommandChanged))); 

... 

private static void OnZoomInCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
{ 
    MyWindow wnd = (MyWindow)d; 

    //Remove the old key binding if there is one. 
    wnd.RemoveInputBinding(e.OldValue as ICommand); 

    //Add the new input binding. 
    if (e.NewValue != null) 
     wnd.InputBindings.Add(new KeyBinding((ICommand)e.NewValue, Key.Add, ModifierKeys.Control)); 
} 

private void RemoveInputBinding(ICommand command) 
{ 
    if (command == null) 
     return; 

    //Find the old binding if there is one. 
    InputBinding oldBinding = null; 

    foreach (InputBinding binding in InputBindings) 
    { 
     if (binding.Command == command) 
     { 
      oldBinding = binding; 
      break; 
     } 
    } 

    //Remove the old input binding. 
    if (oldBinding != null) 
     InputBindings.Remove(oldBinding); 
} 
は、

上記のコードは正確には何ですか?依存関係プロパティで

値であったならば、我々は古いInputBindingを削除し、新しいInputBindingを作成にこれを使用することができますので、それはいつでもプロパティ値の変更を起動しますPropertyChangedCallback方法を有することがオプションである、これは素晴らしいです変更する。あなたのケースでは、DataContextが変更されるたびに値が変更されます。

  1. 古いICommandの古いInputCommandを削除します。

    だから手順は、プロパティの値が変更されたときに、非常に簡単です。

  2. 新しいICommandの新しいInputCommandを追加します。

私は便利なRemoveInputBindingメソッドを作成しました。このメソッドは、他の依存関係プロパティのコードを簡単に再利用できるようにするためのものです。


すべて一緒にこれを適合させるために、あなたのDataContextChangedイベントハンドラであなたは、単にマニュアルバインディング記述する必要があります。

private void MyWindow_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e) 
{ 
    //Bind this.ZoomInCommand to DataContext.ZoomInCommand 
    Binding zoomInCommandBinding = new Binding("ZoomInCommand"); 
    zoomInCommandBinding.Source = DataContext; 
    this.SetBinding(MyWindow.ZoomInCommandProperty, zoomInCommandBinding); 

    ... 
} 

これは、あなたは、もはやDataContextをキャストを心配する必要があることを保証しませんIZoomableViewModelに、をにバインドするには、を試してください。 DataContextにそのようなコマンドがない場合、それはただ黙って失敗します。ただし成功した場合は、PropertyChangedCallbackが実行され、コマンドに対してInputBindingが作成されます。

0

私はうまく動作し、XAMLパーサーの動作を模倣するような単純な解決策を見つけました。基本的には、機能的にズームするために私は、mywindowのコンストラクタで次のコードを置く:もちろん

var zoomInKeyBinding = new KeyBinding { Key = Key.Add, Modifiers = ModifierKeys.Control }; 
BindingOperations.SetBinding(
    zoomInKeyBinding, 
    InputBinding.CommandProperty, 
    new Binding { Path = new PropertyPath("ZoomInCommand") } 
); 
InputBindings.Add(zoomInKeyBinding); 

バウンドのViewModelは適切ZoomInCommandを実装する必要があります。

関連する問題