2010-04-21 36 views
5

幾個月來,我一直在我的SL 3應用程序中成功使用David Justices Default Button example。這種方法基於附屬性。Silverlight 4默認按鈕服務

升級到SL4後,該方法不再起作用了,我得到一個XAML例外:

Unknown parser error: Scanner 2148474880

有沒有人成功地使用這個(或任何其他)在SL4默認按鈕附加的行爲?

有沒有其他的方式來實現SL4中的默認按鈕行爲與新的類可用?

謝謝, 馬克

回答

2

我伸出大衛的做法,允許自定義鍵(默認爲輸入)的一個附加屬性進行設置:

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

我修改原來的財產,然後利用此屬性:

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

所以現在,例如,我可以使用轉義爲關鍵,如果我想(注意,我改變了命名的種類和屬性):

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

我真的很希望會有一個開箱即用解決方案的這種共同的用例在Silverlight 4中,但不幸的是,我不覺得有什麼。

Patrick Cauldwell還有另一個默認按鈕實現。他也在使用附加屬性。

我已經在SL 4應用程序中測試過它,它似乎完成了這項工作。

您可以在這裏找到代碼: http://www.cauldwell.net/patrick/blog/DefaultButtonSemanticsInSilverlightRevisited.aspx

編輯: 我已經調整了大衛正義的代碼來得到它的工作爲Silverlight 4,我只是改變了GetDefaultButton和SetDefaultButton採取與回報一個DefaultButtonService。用法與他網站上的說明相同。 這應該爲你工作:

EDIT2: 新增XAML例如,對於清晰度。

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

如何在XAML應用:

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

謝謝。大衛和帕特里克的方法幾乎完全一樣 - 雖然我很高興看到這個問題不在SL4中,但是我們的應用程序必須有一個特定的場景。感謝您花時間回覆+1 – 2010-04-29 11:31:48

+0

「Get/SetDefaultButton」方法不應該返回/取得一個Button而不是DefaultButtonService嗎?有問題的類型是正在檢索/存儲在屬性中的實際值的類型。我自己做了這個改變,現在它正在工作。 – Trinition 2010-05-26 13:58:43

+0

是的,Trinition,你是對的。如果你想添加一個例子,我會投票你的答案是正確的。如果您願意,可以複製我從下面添加的示例。 – 2010-05-28 11:11:27

0

的問題是由輸入不佳GetDefaultButton方法造成的。這本來是類型爲Button,例如使用:的

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

代替

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

按預期工作。

HTH別人,
馬克

8

對我們來說,最終的解決方案還必須得到解決,其中後備財產沒有被之前的按鈕,點擊發生的歷史(如在所有的MVVM模式)更新的問題.. .. 注:peer.SetFocus();

編輯: 新增XAML例子。

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

如何在XAML應用:

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

這裏是進入被按下時,連接一個默認的按鈕,一個簡單的方法:

出於安全原因,Silverlight將不會讓你叫按鈕處理程序直接在代碼中,所以我們必須創建一個可以調用的新例程,然後讓按鈕處理程序和表單keydown處理程序都調用此例程。

第1步:按常規,把一切都在它的按鈕程序有

private void DoSharedRoutine(){ // do something } 

第2步:有按鈕處理程序調用共享日常

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

步驟3:已KEYDOWN的處理程序包含按鈕的面板調用共享例程

private void MyGrid_KeyDown(object sender, System.Windows.Input.KeyEventArgs e) 
    { 
     if (e.Key == Key.Enter) DoSharedRoutine(); 
    }