2009-12-14 34 views
14

Trong ứng dụng WPF của tôi, tôi muốn đính kèm một cử chỉ đầu vào vào một lệnh để các cử chỉ đầu vào có sẵn trên toàn cầu trong cửa sổ chính, bất kể điều khiển nào có tiêu điểm. Tuy nhiên, trong trường hợp của tôi, tôi muốn ràng buộc Key.PageDown với một lệnh, ngay khi các điều khiển nhất định nhận được tiêu điểm (ví dụ: điều khiển TextBox hoặc TreeView), các điều khiển này nhận được các sự kiện quan trọng và lệnh này không còn được kích hoạt nữa. Các điều khiển này không xác định được CommandBindings hoặc InputBindings cụ thể.WPF: Làm thế nào để ngăn chặn một điều khiển từ ăn cắp một cử chỉ quan trọng?

Đây là cách tôi định nghĩa cử chỉ đầu vào của tôi:

XAML:

<Window x:Class="Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="Window1" Height="300" Width="300" > 
    <StackPanel> 
     <TreeView> 
      <TreeViewItem Header="1"> 
       <TreeViewItem Header="1.1"></TreeViewItem> 
       <TreeViewItem Header="1.2"></TreeViewItem> 
      </TreeViewItem> 
      <TreeViewItem Header="2" ></TreeViewItem> 
     </TreeView> 
     <TextBox /> 
     <Label Name="label1" /> 
    </StackPanel> 
</Window> 

Code:

using System; 
using System.Windows; 
using System.Windows.Input; 

public static class Commands 
{ 
    private static RoutedUICommand _myCommand; 

    static Commands() 
    { 
     _myCommand = new RoutedUICommand("My Command", 
      "My Command", 
      typeof(Commands), 
      new InputGestureCollection() 
       { 
        new KeyGesture(Key.PageDown, ModifierKeys.None) 
       }); 
    } 

    public static ICommand MyCommand 
    { 
     get { return _myCommand; } 
    } 
} 

public partial class Window1 : Window 
{ 
    public Window1() 
    { 
     InitializeComponent(); 

     CommandBinding cb = new CommandBinding(); 
     cb.Command = Commands.MyCommand; 
     cb.Executed += new ExecutedRoutedEventHandler(cb_Executed); 
     cb.CanExecute += new CanExecuteRoutedEventHandler(cb_CanExecute); 
     this.CommandBindings.Add(cb); 
    } 

    void cb_CanExecute(object sender, CanExecuteRoutedEventArgs e) 
    { 
     e.CanExecute = true; 
    } 

    void cb_Executed(object sender, ExecutedRoutedEventArgs e) 
    { 
     this.label1.Content = string.Format("My Command was executed {0}", DateTime.Now); 
    } 
} 

Tôi đã cố gắng bắt sự kiện của cửa sổ PreviewKeyDown và đánh dấu nó như là xử lý này có không phải là hiệu ứng mong muốn. Tôi cũng đặt thuộc tính Focusable thành false. Điều này đã giúp cho điều khiển TextBox, nhưng không cho TreeView (và có hiệu ứng không mong muốn, rằng TextBox không còn có thể được chỉnh sửa nên nó không phải là một giải pháp cho tôi).

Vì vậy, câu hỏi của tôi là làm thế nào tôi có thể xác định một phím tắt hoạt động ở mọi nơi trong cửa sổ chính?

Trả lời

10

Cách giải quyết sau đây dường như có tác dụng mong muốn của việc có lệnh toàn cục đến cửa sổ; Tuy nhiên, tôi vẫn tự hỏi liệu có cách nào dễ dàng hơn để làm điều này trong WPF:

private void Window_PreviewKeyDown(object sender, KeyEventArgs e) 
{ 
    foreach (InputBinding inputBinding in this.InputBindings) 
    { 
     KeyGesture keyGesture = inputBinding.Gesture as KeyGesture; 
     if (keyGesture != null && keyGesture.Key == e.Key && keyGesture.Modifiers == Keyboard.Modifiers) 
     { 
      if (inputBinding.Command != null) 
      { 
       inputBinding.Command.Execute(0); 
       e.Handled = true; 
      } 
     } 
    } 

    foreach (CommandBinding cb in this.CommandBindings) 
    { 
     RoutedCommand command = cb.Command as RoutedCommand; 
     if (command != null) 
     { 
      foreach (InputGesture inputGesture in command.InputGestures) 
      { 
       KeyGesture keyGesture = inputGesture as KeyGesture; 
       if (keyGesture != null && keyGesture.Key == e.Key && keyGesture.Modifiers == Keyboard.Modifiers) 
       { 
        command.Execute(0, this); 
        e.Handled = true; 
       } 
      } 
     } 
    } 
} 

}

+0

Bạn cũng có thể muốn kiểm tra bộ sưu tập InputBindings thay vì CommandBindings. Đôi khi bạn sẽ không có RoutedCommand trong CommandBindings ... – Anvaka

+0

Vâng, tôi quên mất điều đó, cảm ơn cho tip :-) –

+0

Đây là một phao cứu sinh. Cảm ơn bạn! – tltjr

4

Sử dụng PreviewKeyDown là chính xác những gì bạn nên làm ... các "PreviewXYZ" sự kiện được bắn từ dưới lên (vì vậy Window được nó đầu tiên, sau đó điều khiển) ... cho phép bạn làm bất cứ điều gì bạn muốn làm globaly trên cấp độ "Window".

Sau đó, bạn có thể chọn để nói "IsHandled = true" sẽ ngăn không cho nó đi đến điều khiển tiếp theo (theo như bạn quan tâm), nhưng bạn không phải làm điều này. Nếu bạn muốn sự kiện phát ra bong bóng, thì chỉ cần thêm mã của bạn và để "IsHandled" thành false.

+0

Đó là những gì tôi đã thử. Nhưng sau đó cử chỉ chính cũng được lọc và không được chuyển đến cửa sổ. –

+0

P.S .: Điều đó có nghĩa là tôi không thể sử dụng 'InputGestures' trên các lệnh của mình chút nào mà đúng hơn là phải chuyển/trường hợp trên các sự kiện chính trong' PreviewKeyDown' theo cách thủ công? Tôi đã hy vọng rằng nó có thể để tránh điều đó trong WPF ... –

+0

Thành thật mà nói, tôi không phải là rất tốt với InputGestures bản thân mình (sử dụng chúng có thể một lần và tôi không phải là mạnh mẽ). Quan điểm của tôi là bạn có thể làm điều đó với PreviewKeyDown.Tôi biết rằng bạn hoàn toàn có thể đưa ra các lệnh của riêng bạn và sử dụng các cử chỉ ... Tôi đã thực hiện nó, nhưng chỉ trong một bản demo và một thời gian dài trước đây. - Có thể ai đó thông minh hơn tôi sẽ bình luận sớm :) –

2

Đáng tiếc là trong WPF một số điều khiển có một số xử lý bàn phím hardcoded trong nội bộ. Các PreviewKeyDown handler trong cửa sổ chính là câu trả lời cho

Làm thế nào tôi có thể xác định một phím tắt mà làm việc ở khắp mọi nơi trong cửa sổ chính

câu hỏi. Và có, điều đó có nghĩa là bạn có thể muốn chọn chuyển đổi/trường hợp trên các sự kiện chính trong PreviewKeyDown theo cách thủ công ...

Các vấn đề liên quan