2009-09-03 10 views
1

J'essaie d'obtenir un texte sélectionné dans un TextBox incorporé dans un ListView. Cela semble si facile, mais je ne pouvais pas vraiment trouver une solution élégante.WPF: comment capturer le texte sélectionné dans une zone de texte incorporée dans ListView

Lorsque je clique sur l'élément de menu "Créer une règle", je veux obtenir le TextBox dans lequel l'élément de menu réside.

J'apprécie toute aide! J'ai passé beaucoup trop de temps de mon temps sur cette ...

... -> ...

Je veux obtenir le texte dans le code derrière comme ça ...

private void CreateRuleMenuItem_Click(object sender, RoutedEventArgs e) 
    { 
     TextBox txtBox = // ??? 
     string selectedText = txtBox.selectedText; 

Répondre

0

Est-ce un contrôle basé sur un modèle? Si ce n'est pas le cas, vous devriez pouvoir ajouter une étiquette de nom, x:Name="txtTextbox", puis l'adresser directement, txtTextBox.SelectedText.

Puisqu'il s'agit d'un contrôle basé sur un modèle, vous n'avez pas d'accès direct via le nom. Donc, dans votre code-behind, vous pouvez utiliser une méthode comme celle-ci qui trouvera le premier parent de l'élément spécifié d'un type particulier (TextBox). Placez la méthode suivante dans une classe d'aide, ou dans votre code existant:

/// <summary> 
    /// Finds a parent of a given item on the visual tree. 
    /// </summary> 
    /// <typeparam name="T">The type of the queried item.</typeparam> 
    /// <param name="child">A direct or indirect child of the 
    /// queried item.</param> 
    /// <returns>The first parent item that matches the submitted 
    /// type parameter. If not matching item can be found, a null 
    /// reference is being returned.</returns> 
    public static T TryFindParent<T>(this DependencyObject child) 
     where T : DependencyObject 
    { 
     //get parent item 
     DependencyObject parentObject = GetParentObject(child); 

     //we've reached the end of the tree 
     if (parentObject == null) return null; 

     //check if the parent matches the type we're looking for 
     T parent = parentObject as T; 
     if (parent != null) 
     { 
      return parent; 
     } 
     else 
     { 
      //use recursion to proceed with next level 
      return TryFindParent<T>(parentObject); 
     } 
    } 

Ensuite, vous faites juste ce code dans votre gestionnaire d'événements de code:

 MenuItem menuItem = sender as MenuItem; 
     if(menuItem!=null) 
     { 
      TextBox textBox = menuItem.TryFindParent<TextBox>(); 
      if(textBox!=null) 
      { 
       string selectedText = textBox.SelectedText; 
      } 
     } 

Cette méthode est utile dans plusieurs de mes projets , donc je crée une classe UIHelper que je mets ce genre de choses dans ...

Bonne chance,

Jason

0

Merci beaucoup pour votre aide! C'est un contrôle de modèle comme indiqué ci-dessous.

     <GridViewColumn Header="Content"> 
          <GridViewColumn.CellTemplate> 
           <DataTemplate> 
            <TextBox Text="{Binding Path=record_content}" Width="800"> 
             <TextBox.ContextMenu> 
              <ContextMenu> 
               <MenuItem Name="CreateRuleMenuItem" 
                  Header="Create Rule" 
                  Click="CreateRuleMenuItem_Click"/> 
               <MenuItem Name="DeleteRuleMenuItme" 
                  Header="Delete Rule" 
                  Click="DeleteRuleMenuItme_Click"/> 
              </ContextMenu> 
             </TextBox.ContextMenu> 
            </TextBox> 
           </DataTemplate> 
          </GridViewColumn.CellTemplate> 
         </GridViewColumn> 
0

Je voudrais vous recommandons clairement vous en utilisant MVVM et databinding dans ce cas. Je vois que vous avez une classe XXX avec une propriété "record_content" qui est liée à la propriété Text de TextBox.(Je pense que vous avez omis l'option Mode = TwoWay liaison pour assurer que les changements dans la zone de texte modifier la valeur de la propriété record_content)

Vous pouvez ajouter une propriété recordContentSelectedText, lié à la propriété SelectedText de votre zone de texte:

<TextBox [...] SelectedText="{Binding recordContentSelectedText,Mode=TwoWay}"/> 

le datacontext de votre TextBox est une instance de XXX dont le contenu de l'enregistrement contient le contenu TextBox .... Et le ContextMenu et ses éléments ont le même DataContext!

Si la valeur de la propriété est correctement mis à jour par votre databinding, il sera très facile:

var data = this.DataContext as XXX; 
var selectedText = this.recordContentSelectedText; 

Il ne fonctionnera que si votre DataContext est lié seulement à une zone de texte dans la liste. Sinon, la synchronisation du texte sélectionné TextBox se produira comme un effet secondaire (je ne sais pas si vous comprenez ce que je veux dire, mais cela pourrait être un problème ou non, selon le comportement que vous attendez de votre application)

Questions connexes