2013-01-10 3 views
1

Je travaille sur une application Windows Phone utilisant Silverlight C# et XAML. Ma page contient un contrôle ListBox qui affiche une liste d'objets de données que l'utilisateur peut manipuler, c'est-à-dire ajouter/renommer/supprimer.Evénement Silverlight TextBox VisibilityChanged

Je l'ai travail que l'ajout/renommage des éléments se fait en place, soit en échangeant un TextBlock pour une zone de texte en fonction de l'état de l'objet (bool IsEditable propriété) et faisant usage d'un paramétrés VisibilityConverter pour gérer les états de visibilité opposés.

<UserControl.Resources> 
    <local:VisibilityConverter x:Key="VisibilityConverter" True="Visible" False="Collapsed"/> 
    <local:VisibilityConverter x:Key="InvertedVisibility" True="Collapsed" False="Visible"/> 
</UserControl.Resources> 
... 
<TextBlock Text="{Binding Name}" Visibility="{Binding IsEditable, Converter={StaticResource InvertedVisibility}}" /> 
<TextBox Text="{Binding Name}" Visibility="{Binding IsEditable, Converter={StaticResource VisibilityConverter}}"/> 

La chose est que je veux aussi la zone de texte pour saisir automatiquement mise au point quand il devient visible, de sorte que le clavier à l'écran apparaît sans que l'utilisateur ait à exploiter la zone de texte.

Comme il n'y a pas d'événement VisibilityChanged sur une zone de texte régulière, je subclassed TextBox à TextBox2 et ajouté mon:

public class TextBox2 : TextBox 
{ 
    public TextBox2() 
    { 
     DefaultStyleKey = typeof(TextBox); 
    } 

    public static readonly DependencyProperty VisibilityChangedProperty = DependencyProperty.Register(
     "VisibilityChanged", 
     typeof(string), 
     typeof(TextBox2), 
     new PropertyMetadata("Set the VisibilityChanged event handler")); 

    public event VisibilityChangedEventHandler VisibilityChanged; 

    public delegate void VisibilityChangedEventHandler(object sender, EventArgs e); 

    public new Visibility Visibility 
    { 
     get 
     { 
      return base.Visibility; 
     } 
     set 
     { 
      if (base.Visibility != value) 
      { 
       base.Visibility = value; 
       VisibilityChanged(this, new EventArgs()); 
      } 
     } 
    } 
} 

Maintenant, mon XAML ressemble à ceci:

<TextBlock Text="{Binding Name}" Visibility="{Binding IsEditable, Converter={StaticResource InvertedVisibility}}"/> 
<local:TextBox2 Text="{Binding Name}" Visibility="{Binding IsEditable, Converter={StaticResource VisibilityConverter}}" VisibilityChanged="ListEdit_VisibilityChanged"/> 

Et le gestionnaire d'événements comme ceci:

void ListEdit_VisibilityChanged(object sender, EventArgs e) 
{ 
    TextBox textBox = (TextBox)sender; 
    if (textBox.Visibility == System.Windows.Visibility.Collapsed) 
     return; 
    textBox.Focus(); 
} 

Le TextBox2 rend correctement et se comporte comme un T extBox à l'exécution, mais mon gestionnaire d'événements VisibilityChanged ne déclenche pas lorsque la liaison de données retourne la valeur IsEditable.

IsEditable définit la visibilité et le TextBox2 devient visible correctement, de sorte que la liaison de données fonctionne.

Je peux déclencher l'événement par programmation en obtenant l'instance TextBox2 et en définissant la visibilité de cela dans le code. Cela fonctionne aussi. Mais ce scénario de liaison de données étant responsable de la définition de la visibilité semble ne pas fonctionner.

Des idées pourquoi pas?

Répondre

0

Voici comment ma classe TextBox2 regarde maintenant :

public class TextBox2 : TextBox 
{ 
    public event VisibilityChangedEventHandler VisibilityChanged; 
    public delegate void VisibilityChangedEventHandler(object sender, EventArgs e); 
    public static readonly DependencyProperty VisibilityChangedProperty = DependencyProperty.Register(
     "VisibilityChanged", typeof(VisibilityChangedEventHandler), typeof(TextBox2), null); 

    static readonly DependencyProperty MirrorVisibilityProperty = DependencyProperty.Register(
     "MirrorVisibility", typeof(Visibility), typeof(TextBox2), new PropertyMetadata(MirrorVisibilityChanged)); 

    public TextBox2() 
    { 
     SetBinding(TextBox2.MirrorVisibilityProperty, new Binding("Visibility") { Source = this }); 
    } 

    static void MirrorVisibilityChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) 
    { 
     ((TextBox2)obj).VisibilityChanged(obj, null); // raise event 
    } 
} 
2

Voici 2 solutions que j'utilise.

La solution 1 n'a pas besoin de sous-classe, mais la solution 2 est plus réutilisable.

. Vous pouvez vous abonner à l'événement Loaded du TextBox, et forcer une mise au point, comme ceci:

void TextBox_Loaded_Focus(object sender, System.Windows.RoutedEventArgs e) { 
     ForceFocusControl((Control)sender);    
    } 

    void ForceFocusControl(Control control) { 

     control.Focus(); 

     if (FocusManager.GetFocusedElement() != control) { 

      Dispatcher.BeginInvoke(() => ForceFocusControl(control)); 
     } 
    } 

Cette solution va dans une boucle récursive cependant, vous pouvez ajouter des contrôles pour le rendre plus sûr.

.Gardez votre sous-classe TextBox2, et plutôt créer une propriété de dépendance MyVisibility privée qui vous lient à la propriété Visibility de la classe de base, mais également spécifier un gestionnaire DependencyProperty_Changed, comme ceci:

/// <summary> 
    /// <see cref="TextBox2"/> will focus itself when it becomes visible. 
    /// </summary> 
    public sealed class TextBox2 : TextBox { 

     public TextBox2() { 

      SetBinding(TextBox2.MyVisibilityProperty, new Binding("Visibility") { Source = this }); 
     } 

     static readonly DependencyProperty MyVisibilityProperty = DependencyProperty.Register(
      /* name = */ "MyVisibilityProperty", 
      /* property type = */ typeof(Visibility), 
      /* owner type = */ typeof(TextBox2), 
      /* meta = */ new PropertyMetadata(MyVisibilityProperty_Changed)); 

     static void MyVisibilityProperty_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e) { 

      TextBox2 TextBox2 = (TextBox2)d; 

      if (TextBox2.Visibility == Visibility.Visible) { 
       TextBox2.Focus(); 
      } 
     } 
    } 
+0

Merci, Martin! J'ai fusionné votre technique _property mirroring_ avec mon code de gestionnaire d'événement externe et cela fonctionne parfaitement. – larryk78

+0

De rien! –

Questions connexes