2010-03-17 8 views
2

J'essaie de trouver la meilleure façon de sélectionner tout le texte dans un TextBox la première fois que le contrôle est chargé. J'utilise le modèle MVVM, donc j'utilise la liaison bidirectionnelle pour la propriété Text du TextBox à une chaîne sur mon ViewModel. J'utilise ce TextBox pour "renommer" quelque chose qui a déjà un nom, donc je voudrais sélectionner l'ancien nom quand le contrôle se charge afin qu'il puisse facilement être supprimé et renommé. Le texte initial (ancien nom) est rempli en le définissant dans mon ViewModel et il est ensuite reflété dans le TextBox après la liaison de données terminée.Sélectionnez le texte initial dans un TextBox Silverlight

Ce que je vraiment aime faire est quelque chose comme ceci:

<TextBox x:Name="NameTextBox" Text="{Binding NameViewModelProperty, Mode=TwoWay}" SelectedText="{Binding NameViewModelProperty, Mode=OneTime}" /> 

Fondamentalement, il suffit d'utiliser le texte entier comme SelectedText avec OneTime obligatoire. Toutefois, cela ne fonctionne pas puisque le SelectedText n'est pas un DependencyProperty. Je ne suis pas complètement contre l'ajout du code de sélection dans le code-behind de ma vue, mais mon problème dans ce cas est de déterminer quand la liaison de texte initiale est terminée. Le TextBox commence toujours vide, donc il ne peut pas être fait dans le constructeur. L'événement TextChanged semble uniquement se déclencher lorsqu'un utilisateur entre un nouveau texte, pas lorsque le texte est modifié à partir de la liaison initiale du ViewModel.

Toutes les idées sont grandement appréciées!

Répondre

3

Dan,

J'ai écrit une classe dérivée très simple, TextBoxEx, qui offre cette fonctionnalité. La classe TextBoxEx dérive de TextBox et peut être référencée dans XAML pour tous vos TextBox. Il n'y a pas de méthodes à appeler. Il écoute juste pour les événements Focus et sélectionne son propre texte. Très simple.

Utilisation est la suivante:

En XAML, l'ensemble de référence où vous implémentez la classe TextBoxEx ci-dessous, et d'ajouter autant d'éléments de TextBoxEx que vous avez besoin. L'exemple ci-dessous utilise la liaison de données pour afficher un nom d'utilisateur.

<UserControl x:Class="MyApp.MainPage" 
    xmlns="http://schemas.microsoft.com/client/2007"  
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
    xmlns:c="clr-namespace:ClassLibrary;assembly=ClassLibrary" 
> 
.  
.  
.  
<c:TextBoxEx x:Name="NameTextBox" Text="{Binding NameViewModelProperty, Mode=TwoWay}" Width="120" /> 

Ce code fonctionne ci-dessous avec Silverlight 3.

using System.Windows; 
using System.Windows.Controls; 

namespace ClassLibrary 
{ 
    // This TextBox derived class selects all text when it receives focus 
    public class TextBoxEx : TextBox 
    { 
     public TextBoxEx() 
     { 
      base.GotFocus += OnGotFocus; 
     } 

     private void OnGotFocus(object sender, RoutedEventArgs e) 
     { 
      base.SelectAll(); 
     } 
    } 
} 

Bonne chance.

+0

Je ne crois pas que le sous-classement était vraiment nécessaire pour cela, mais l'appel de SelectAll() sur l'événement GotFocus de TextBox a effectivement obtenu ce que je voulais même avec du texte lié aux données. Je ne vois aucune raison réelle pour que ce soit une sous-classe, je l'ai juste fait dans mon code-behind et il pourrait facilement être refactorisé dans un comportement de mélange si je voulais obtenir plus de MVVMish. Merci! –

2

Je laisse la solution de Jim comme réponse, car l'appel SelectAll() sur l'événement GotFocus de la TextBox a fait l'affaire.

En fait, j'ai fini par faire un Blend TriggerAction et un EventTrigger pour faire ceci au lieu de sous-classer le TextBox ou de le faire en code-behind. C'était vraiment simple à faire et agréable de pouvoir garder la logique de comportement encapsulée et juste l'ajouter de manière déclarative en XAML à un TextBox existant.

affichage Juste ce au cas où quelqu'un d'autre vient sur ce fil et se intéresse:

XAML:

<TextBox x:Name="NameTextBox" Text="{Binding NameViewModelProperty, Mode=TwoWay}"> 
    <i:Interaction.Triggers> 
     <i:EventTrigger EventName="GotFocus"> 
      <local:SelectAllAction/> 
     </i:EventTrigger> 
    </i:Interaction.Triggers> 
</TextBox> 

C#

public class SelectAllAction : TriggerAction<TextBox> 
{ 
    protected override void Invoke(object parameter) 
    { 
     if (this.AssociatedObject != null) 
     { 
      this.AssociatedObject.SelectAll(); 
     } 
    } 
} 
+0

Est-ce pour WPF de Silverlight? Lorsque j'ai essayé d'étendre TriggerAction avec un type, le compilateur s'est plaint que TriggerAction n'est pas générique, donc il ne peut pas accepter un type. – Trinition

+0

Ceci est pour Silveright, je ne suis pas sûr si les déclencheurs de mélange et les actions sont disponibles pour WPF. Vous devez vous assurer que vous héritez de System.Windows.Interactivity.TriggerAction <> pas System.Windows.TriggerAction. Vous devrez référencer la DLL à partir du SDK Blend. –

1

Je veux juste ajouter un lien I trouvé à ce sujet - voici un fantastic discussion (lire les commentaires) sur Be haviours vs sous-classe vvs propriétés attachées ...

Questions connexes