La sélection d’un élément de zone de texte dans une zone de liste ne modifie pas l’élément sélectionné de la liste.

J’ai une liste de wpf qui affiche une liste de zones de texte. Lorsque je clique sur la zone de texte, la sélection de la zone de liste ne change pas. Je dois cliquer à côté de la zone de texte pour sélectionner l’élément de liste. Y a-t-il une propriété que je dois définir pour que la zone de texte transfère l’événement de clic à la Listbox?

Veillez à utiliser TargetType approprié: ListViewItem, ListBoxItem ou TreeViewItem.

 

Nous utilisons le style suivant pour définir un PreviewGotKeyboardFocus qui gère tous les événements du contrôle TextBox et des ComboBoxes, par exemple:

     

Et puis nous sélectionnons la ligne dans le code derrière:

  protected void SelectCurrentItem(object sender, KeyboardFocusChangedEventArgs e) { ListViewItem item = (ListViewItem) sender; item.IsSelected = true; } 

Je n’ai pas assez de représentants pour commenter, alors je publie mon commentaire en réponse. La solution de Grazer ci-dessus ne fonctionne pas dans les cas où vous avez un autre contrôle tel qu’un Button qui nécessite le SelectedItem . En effet, selon le Style Trigger , IsKeyboardFocusWithin devient faux lorsque vous cliquez sur ce Button et que le SelectedItem devient nul.

J’ai utilisé similaire à la solution de Robert, mais sans code derrière (en utilisant le comportement attaché).

Faire cela,

Premier. Créez une classe séparée FocusBehaviour:

 using System.Windows; using System.Windows.Controls; using System.Windows.Media; namespace MyBehaviours { public class FocusBehaviour { #region IsFocused public static bool GetIsFocused(Control control) { return (bool) control.GetValue(IsFocusedProperty); } public static void SetIsFocused(Control control, bool value) { control.SetValue(IsFocusedProperty, value); } public static readonly DependencyProperty IsFocusedProperty = DependencyProperty.RegisterAttached( "IsFocused", typeof(bool), typeof(FocusBehaviour), new UIPropertyMetadata(false, IsFocusedPropertyChanged)); public static void IsFocusedPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) { var control = sender as Control; if (control == null || !(e.NewValue is bool)) return; if ((bool)e.NewValue && !(bool)e.OldValue) control.Focus(); } #endregion IsFocused #region IsListBoxItemSelected public static bool GetIsListBoxItemSelected(Control control) { return (bool) control.GetValue(IsListBoxItemSelectedProperty); } public static void SetIsListBoxItemSelected(Control control, bool value) { control.SetValue(IsListBoxItemSelectedProperty, value); } public static readonly DependencyProperty IsListBoxItemSelectedProperty = DependencyProperty.RegisterAttached( "IsListBoxItemSelected", typeof(bool), typeof(FocusBehaviour), new UIPropertyMetadata(false, IsListBoxItemSelectedPropertyChanged)); public static void IsListBoxItemSelectedPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) { var control = sender as Control; DependencyObject p = control; while (p != null && !(p is ListBoxItem)) { p = VisualTreeHelper.GetParent(p); } if (p == null) return; ((ListBoxItem)p).IsSelected = (bool)e.NewValue; } #endregion IsListBoxItemSelected } } 

Seconde. Ajouter un style dans la section des ressources (mon style est arrondi en noir sur le focus). Formateur de notification pour la propriété FocusBehaviour.IsListBoxItemSelected. Vous devriez le référencer dans xmlns:behave="clr-namespace:MyBehaviours"

`

   

`

Troisième. (facultatif, pour la tâche inverse)

Vous rencontrerez, sinon toutes, des tâches inverses – en vous concentrant sur TextBox lorsque ListBoxItem sera sélectionné. Je recommande d’utiliser une autre propriété de la classe Behavior, IsFocused. Voici un exemple de modèle pour ListBoxItem , notez Property="behave:FocusBehaviour.IsFocused" et FocusManager.IsFocusScope="True"

            

J’utilise un gestionnaire de classe pour définir ce comportement. Faire cela de cette manière corrigera toutes les vues de liste dans l’application. Je ne sais pas pourquoi ce n’est pas le comportement par défaut.

Dans votre App.xaml.cs, ajoutez ce qui suit à OnStartup:

 protected override void OnStartup(StartupEventArgs e) { EventManager.RegisterClassHandler(typeof (ListViewItem), ListViewItem.PreviewGotKeyboardFocusEvent, new RoutedEventHandler((x,_) => (x as ListViewItem).IsSelected = true)); } 

Y a-t-il une propriété que je dois définir pour que la zone de texte transfère l’événement de clic à la Listbox?

Ce n’est pas une propriété simple, mais vous pouvez gérer l’événement GotFocus sur votre TextBox , puis utiliser VisualTreeHelper pour rechercher le ListBoxItem et le sélectionner:

 private void TextBox_GotFocus(object sender, RoutedEventArgs e) { TextBox myTextBox = sender as TextBox; DependencyObject parent = VisualTreeHelper.GetParent(myTextBox); while (!(parent is ListBoxItem)) { parent = VisualTreeHelper.GetParent(parent); } ListBoxItem myListBoxItem = parent as ListBoxItem; myListBoxItem.IsSelected = true; } 

La manière la plus simple de le faire est d’utiliser l’événement PreviewMouseDown et de définir la propriété IsSelected du parent basé sur un modèle. Comme les événements d’aperçu s’affichent, le composant ListBoxItem traitera l’événement dès que l’utilisateur clique sur la zone de texte, la zone de liste déroulante ou tout autre contrôle sur lequel vous avez défini l’événement.

Une chose intéressante à ce propos est que vous pouvez utiliser le même événement pour tous les types de contrôles, car ils dérivent tous de l’élément Framework. En outre, si vous définissez IsSelected (au lieu de définir SelectedItem), plusieurs éléments seront sélectionnés lorsque vous définissez le mode SelectionMode de la liste à “Extended”, ce qui pourrait ou non être ce que vous recherchez.

c’est à dire:

code c #

 private void Element_PreviewMouseDown(object sender, MouseButtonEventArgs e) { ((sender as FrameworkElement).TemplatedParent as ListBoxItem).IsSelected = true; } 

xaml

  ...   ... 

c’est la réponse que vous recherchez: Sélection d’un ListBoxItem lorsque sa zone de liste déroulante interne est active

Ce qui suit est une simplification de la réponse de @ Ben sans avoir à remplacer le DataTemplate. Il peut même être appliqué comme un style statique. Testé avec un ListView contenant un GridView > GridViewColumn > TextBox .

Exemple:

    

La Listbox gère la sélection des éléments mais ne connaît pas le focus de la zone de texte intégrée. Si vous souhaitez modifier la sélection chaque fois qu’une zone de texte obtient le focus de saisie, vous devez modifier la sélection de la zone de liste manuellement.

Je ne suis pas tout à fait sûr que vous voudriez définir la sélection directement comme décrit dans la réponse précédente parce que je pense que cela briserait la sélection multiple et d’autres scénarios

. Vous pourriez vouloir essayer de restyler un bouton comme ci-dessous et voir ce qui se passe.

  

Votre pas très précis sur votre situation initiale. Mais je suppose que vous utilisez DataBinding et un ItemTemplate. Thats imho un moyen facile de le faire, aussi bien si votre débutant sur ce sujet. Cela devrait fonctionner:

        

 private void TextBox_GotFocus(object sender, RoutedEventArgs e) { myListBox.SelectedItem = (sender as TextBox).Tag; /* Maybe you need to cast to the type of the objects contained in the collection(bound as ItemSource above) */ } 

Essayez ce code:

 foreach (object item in this.listBox1.Items) { if (textbox1.text.equals(item.toSsortingng())) { //show error message; break } } 

Ancienne discussion, mais peut-être que ma réponse aide les autres …

La solution de Ben a le même problème que la solution de Grazer. La mauvaise chose est que la sélection dépend du focus [clavier] de la zone de texte. Si vous avez un autre contrôle sur votre boîte de dialog (c.-à-d. Un bouton), le focus est perdu lorsque vous cliquez sur le bouton et que le listboxitem est désactivé (SelectedItem == null). Vous avez donc un comportement différent en cliquant sur l’élément (en dehors de la zone de texte) et en cliquant dans la zone de texte. C’est très fastidieux à manipuler et semble très étrange.

Je suis certain qu’il n’y a pas de solution XAML pure pour cela. Nous avons besoin de code-behind pour cela. La solution est proche de ce que Mark a suggéré.

(Dans mon exemple, j’utilise ListViewItem au lieu de ListBoxItem, mais la solution fonctionne pour les deux).

Code-behind:

 private void Element_PreviewMouseDown(object sender, MouseButtonEventArgs e) { var frameworkElement = sender as FrameworkElement; if (frameworkElement != null) { var item = FindParent(frameworkElement); if (item != null) item.IsSelected = true; } } 

avec FindParent (extrait de http://www.infragistics.com/community/blogs/blagunas/archive/2013/05/29/find-the-parent-control-of-a-specific-type-in-wpf-and -silverlight.aspx ):

 public static T FindParent(DependencyObject child) where T : DependencyObject { //get parent item DependencyObject parentObject = VisualTreeHelper.GetParent(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; return FindParent(parentObject); } 

Dans mon DataTemplate: