2010-04-21 31 views
5

Trong một vài tháng, tôi đã sử dụng thành công David Justices Default Button example trong ứng dụng SL 3 của mình. Cách tiếp cận này dựa trên tài sản đính kèm.Dịch vụ nút mặc định Silverlight 4

Sau khi nâng cấp lên SL4, cách tiếp cận không còn hoạt động, và tôi nhận được một ngoại lệ XAML:

Unknown parser error: Scanner 2148474880

Có ai thành công sử dụng này (hoặc bất kỳ khác) nút mặc định hành vi đính kèm trong SL4?

Có cách nào khác để đạt được hành vi nút mặc định trong SL4 với các lớp mới có sẵn không?

Cảm ơn, Đánh dấu

Trả lời

2

tôi mở rộng cách tiếp cận của David bằng cách cho phép một phím tùy chỉnh (mặc định để Enter) để được đặt trong một additional property:

public static DependencyProperty ButtonKeyProperty = DependencyProperty.RegisterAttached(
     "ButtonKey", 
     typeof(Key), 
     typeof(Defaults), 
     new PropertyMetadata(Key.Enter, ButtonChanged)); 

    public static void SetButtonKey(DependencyObject dependencyObj, Key key) 
    { 
     dependencyObj.SetValue(ButtonKeyProperty, key); 
    } 

    public static Key GetButtonKey(DependencyObject dependencyObj) 
    { 
     return (Key)dependencyObj.GetValue(ButtonKeyProperty); 
    } 

tôi đã sửa đổi thuộc tính gốc để tận dụng thuộc tính này:

Key key = GetButtonKey(dependencyObj); 
    if (button.IsEnabled && keyEvent.Key == key) 
     ... 

Vì vậy, bây giờ, ví dụ, tôi có thể sử dụng thoát là chìa khóa nếu tôi muốn (lưu ý tôi đã thay đổi tên của các lớp và các thuộc tính):

... UI:Defaults.Button="{Binding ElementName=myButton}" UI:Defaults.ButtonKey="Escape" ... 
3

Tôi đã thực sự hy vọng rằng sẽ có một ra khỏi dung dịch hộp cho một use-case thông thường như vậy trong Silverlight 4, nhưng tiếc là tôi không nghĩ rằng có.

Có một triển khai Nút mặc định khác của Patrick Cauldwell. Anh ấy cũng sử dụng Thuộc tính được đính kèm.

Tôi đã thử nghiệm điều này trong một ứng dụng SL 4 và dường như thực hiện công việc.

Bạn có thể tìm mã ở đây: http://www.cauldwell.net/patrick/blog/DefaultButtonSemanticsInSilverlightRevisited.aspx

Edit: tôi đã điều chỉnh đang David Justice để làm cho nó làm việc cho Silverlight 4. Tôi vừa mới thay đổi GetDefaultButton và SetDefaultButton lấy và trả lại một DefaultButtonService. Cách sử dụng giống như được ghi trên trang web của anh ấy. Điều này sẽ phù hợp với bạn:

Chỉnh sửa2: Thêm ví dụ XAML để làm rõ.

public class DefaultButtonService 
    { 
     public static DependencyProperty DefaultButtonProperty = 
      DependencyProperty.RegisterAttached("DefaultButton", 
               typeof(Button), 
               typeof(DefaultButtonService), 
               new PropertyMetadata(null, DefaultButtonChanged)); 

     private static void DefaultButtonChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
     { 
      var uiElement = d as UIElement; 
      var button = e.NewValue as Button; 
      if (uiElement != null && button != null) 
      { 
       uiElement.KeyUp += (sender, arg) => 
       { 
        if (arg.Key == Key.Enter) 
        { 
         var peer = new ButtonAutomationPeer(button); 
         var invokeProv = 
          peer.GetPattern(PatternInterface.Invoke) as IInvokeProvider; 
         if (invokeProv != null) 
          invokeProv.Invoke(); 
        } 
       }; 
      } 
     } 

     public static DefaultButtonService GetDefaultButton(UIElement obj) 
     { 
      return (DefaultButtonService)obj.GetValue(DefaultButtonProperty); 
     } 

     public static void SetDefaultButton(DependencyObject obj, DefaultButtonService button) 
     { 
      obj.SetValue(DefaultButtonProperty, button); 
     }   
    } 

Làm thế nào để áp dụng trong XAML:

<StackPanel> 
    <TextBox DinnerConfig:DefaultButtonService.DefaultButton="{Binding ElementName=MyButton}" 
       Text="Press Enter" /> 
    <Button x:Name="MyButton" 
      Content="Click me" /> 
</StackPanel> 
+0

Cảm ơn. Cách tiếp cận của David và Patricks khá giống nhau - mặc dù tôi rất vui khi thấy rằng vấn đề không phải với SL4, phải là một kịch bản cụ thể liên quan đến ứng dụng của chúng tôi. Cảm ơn bạn đã dành thời gian trả lời +1 –

+0

Không phải phương thức "Get/SetDefaultButton" trả về/nhận một Nút thay vì một DefaultButtonService? Loại được đề cập là loại giá trị thực được truy xuất/lưu trữ trong thuộc tính. Tôi đã tự mình thay đổi và nó đang hoạt động. – Trinition

+0

Có, Trinition, bạn là chính xác. Nếu bạn muốn thêm một ví dụ, tôi sẽ bình chọn câu trả lời của bạn là chính xác. Bạn có thể sao chép ví dụ của tôi được thêm từ bên dưới nếu bạn muốn. –

0

Vấn đề này được gây ra bởi một kém gõ GetDefaultButton phương pháp. Đây lẽ ra phải được đánh máy như Button, ví dụ sử dụng:

public static Button GetDefaultButton(UIElement obj) 
    { 
     return (Button)obj.GetValue(DefaultButtonProperty); 
    } 

thay vì

public static DefaultButtonService GetDefaultButton(UIElement obj)  
    {  
     return (DefaultButtonService)obj.GetValue(DefaultButtonProperty);  
    } 

công trình như mong đợi.

HTH người khác,
Đánh dấu

8

Các giải pháp cuối cùng cho chúng ta cũng phải có được xung quanh vấn đề hợp tài sản hậu thuẫn đã không được cập nhật trước khi occuring nút bấm (như trong tất cả các mô hình MVVM) .. .. Lưu ý:peer.SetFocus();

Edit: Added XAML ví dụ.

public static class DefaultButtonService 
{ 
    public static DependencyProperty DefaultButtonProperty = 
      DependencyProperty.RegisterAttached("DefaultButton", 
               typeof(Button), 
               typeof(DefaultButtonService), 
               new PropertyMetadata(null, DefaultButtonChanged)); 

    private static void DefaultButtonChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { 
     var uiElement = d as UIElement; 
     var button = e.NewValue as Button; 
     if (uiElement != null && button != null) { 
      uiElement.KeyUp += (sender, arg) => { 
       var peer = new ButtonAutomationPeer(button); 

       if (arg.Key == Key.Enter) { 
        peer.SetFocus(); 
        uiElement.Dispatcher.BeginInvoke((Action)delegate { 

         var invokeProv = 
          peer.GetPattern(PatternInterface.Invoke) as IInvokeProvider; 
         if (invokeProv != null) 
          invokeProv.Invoke(); 
        }); 
       } 
      }; 
     } 

    } 

    public static Button GetDefaultButton(UIElement obj) { 
     return (Button)obj.GetValue(DefaultButtonProperty); 
    } 

    public static void SetDefaultButton(DependencyObject obj, Button button) { 
     obj.SetValue(DefaultButtonProperty, button); 
    }  
} 

Làm thế nào để áp dụng trong XAML:

<StackPanel> 
    <TextBox DinnerConfig:DefaultButtonService.DefaultButton="{Binding ElementName=MyButton}" 
       Text="Press Enter" /> 
    <Button x:Name="MyButton" 
      Content="Click me" /> 
</StackPanel> 
0

Dưới đây là một cách dễ dàng để dây một nút mặc định khi nhập được nhấn:

Vì lý do an ninh, Silverlight sẽ không cho phép bạn gọi một nút xử lý trực tiếp trong mã, vì vậy chúng tôi phải tạo một thói quen mới có thể được gọi, sau đó có trình xử lý nút và trình xử lý khóa biểu mẫu cả hai đều gọi thường trình này.

Bước 1: làm cho một thói quen và đặt mọi thứ trong nó rằng thói quen nút có

private void DoSharedRoutine(){ // do something } 

Bước 2: đã gọi nút điều khiển chia sẻ thói quen

private void Login_Click(object sender, System.Windows.RoutedEventArgs e) 
    { 
     DoSharedRoutine(); 
    } 

Bước 3: đã KeyDown handler của bảng điều khiển chứa nút của bạn gọi là thường lệ được chia sẻ

private void MyGrid_KeyDown(object sender, System.Windows.Input.KeyEventArgs e) 
    { 
     if (e.Key == Key.Enter) DoSharedRoutine(); 
    } 
Các vấn đề liên quan