2010-04-21 18 views
5

Depuis quelques mois, j'utilise avec succès David Justices Default Button example dans mon application SL 3. Cette approche est basée sur une propriété jointe.Silverlight 4 Service de bouton par défaut

Après la mise à niveau SL4, l'approche ne fonctionne plus, et je reçois une exception XAML:

Unknown parser error: Scanner 2148474880

Quelqu'un at-il utilisé avec succès ce (ou tout autre) bouton par défaut des comportements attachés à SL4?

Existe-t-il un autre moyen d'obtenir un comportement de bouton par défaut dans SL4 avec les nouvelles classes disponibles?

Merci, Mark

Répondre

2

Je tendis l'approche de David en permettant une clé personnalisée (par défaut à Enter) à régler dans une propriété supplémentaire:

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

I a modifié la propriété d'origine pour exploiter cette propriété:

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

Alors maintenant, par exemple, je peux utiliser Évasion comme la clé si je veux (note j'ai changé DÉSIGNÉ des classes et propriétés):

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

J'espérais vraiment qu'il y aurait une de la solution de la boîte pour un tel cas d'utilisation courante dans Silverlight 4, mais malheureusement, je ne pense pas qu'il y ait.

Il existe une autre implémentation de bouton par défaut par Patrick Cauldwell. Il utilise également les propriétés attachées.

J'ai testé cela dans une application SL 4 et cela semble faire l'affaire.

Vous pouvez trouver le code ici: http://www.cauldwell.net/patrick/blog/DefaultButtonSemanticsInSilverlightRevisited.aspx

Edit: J'ai peaufiné le code de David Justice pour le faire fonctionner pour Silverlight 4. Je viens de changer le GetDefaultButton et SetDefaultButton prendre et retour un DefaultButtonService. L'utilisation est la même que celle indiquée sur son site Web. Cela devrait fonctionner pour vous:

Edit2: Ajouté XAML exemple pour plus de clarté.

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

Comment appliquer en XAML:

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

Merci. Les approches de David et Patrick sont à peu près les mêmes - même si je suis content de voir que le problème n'est pas avec SL4, un scénario particulier doit être lié à notre application. Merci d'avoir pris le temps de répondre +1 –

+0

Les méthodes "Get/SetDefaultButton" ne devraient-elles pas renvoyer/prendre un bouton au lieu d'un DefaultButtonService? Le type en question est le type de la valeur réelle récupérée/stockée dans la propriété. J'ai fait ce changement moi-même et ça marche maintenant. – Trinition

+0

Oui, Trinition, vous avez raison. Si vous voulez ajouter un exemple, je voterai votre réponse comme correcte. Vous pouvez copier mon exemple ajouté ci-dessous si vous le souhaitez. –

0

La question a été causée par une méthode GetDefaultButton mal tapé. Cela aurait dû être tapé comme Button, par exemple en utilisant:

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

au lieu de

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

fonctionne comme prévu.

quelqu'un HTH autre,
Mark

8

La solution finale pour nous a également de contourner le problème où la propriété de support n'a pas été mis à jour avant le bouton clic se produisant (comme dans tous les modèles MVVM) .. .. note:peer.SetFocus();

Edit: Ajouté XAML exemple.

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

Comment appliquer en XAML:

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

Voici un moyen facile de câbler un bouton par défaut lorsque vous appuyez sur Entrée:

Pour des raisons de sécurité, silverlight ne vous laissera pas appeler un gestionnaire de boutons directement dans le code, nous devons donc créer une nouvelle routine qui peut être appelée, puis demander au gestionnaire de boutons et au gestionnaire de raccourci de formulaire d'appeler cette routine.

Étape 1: faire une routine et mettre tout ce que la routine bouton avait

private void DoSharedRoutine(){ // do something } 

Étape 2: ont le bouton d'appel de gestionnaire de routine partagée

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

Étape 3: ont KEYDOWN gestionnaire de votre panneau qui contient votre bouton appelle la routine partagée

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