Selecting a text field item in a list does not change the selected list item

I have a wpf list displaying a list of text fields. When I click on the text box, the selection of the list does not change. I have to click next to the TextBox to select a list item. Is there any property that I need to set for a text field to forward the click event to the list?

+43
c # wpf xaml listbox selecteditem
Mar 17 '09 at 9:29
source share
14 answers

Be sure to use the appropriate TargetType: ListViewItem, ListBoxItem, or TreeViewItem.

<Style TargetType="ListViewItem"> <Style.Triggers> <Trigger Property="IsKeyboardFocusWithin" Value="true"> <Setter Property="IsSelected" Value="true" /> </Trigger> </Style.Triggers> </Style> 
+37
Nov 03 2018-11-11T00:
source share

We use the following style to set PreviewGotKeyboardFocus, which handles all the events of the TextBox and ComboBoxes control, etc.:

  <ListView.ItemContainerStyle> <Style TargetType="ListViewItem"> <EventSetter Event="PreviewGotKeyboardFocus" Handler="SelectCurrentItem"/> </Style> </ListView.ItemContainerStyle> 

And then we select the line in the code behind:

  protected void SelectCurrentItem(object sender, KeyboardFocusChangedEventArgs e) { ListViewItem item = (ListViewItem) sender; item.IsSelected = true; } 
+35
May 14 '09 at 12:55
source share

I do not have enough comments for comments, so I am posting my comment as an answer. The Grazer solution above does not work in cases where you have another control, such as Button , which requires a SelectedItem . This is because, according to the Style Trigger , the IsKeyboardFocusWithin value becomes false when the Button clicked, and the SelectedItem becomes zero.

+6
Dec 23 '13 at 1:07
source share

I used similarly to Robert's solution, but without code (using the attached behavior).

To do this,

Firstly. Create a separate FocusBehaviour class:

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

Secondly. Add a style to the resources section (my style is rounded in the center). Setter notification for the FocusBehaviour.IsListBoxItemSelected property. You must reference it in xmlns:behave="clr-namespace:MyBehaviours"

`

  <Style x:Key="PreviewTextBox" BasedOn="{x:Null}" TargetType="{x:Type TextBox}"> <Setter Property="BorderThickness" Value="1"/> <Setter Property="Padding" Value="1"/> <Setter Property="AllowDrop" Value="true"/> <Setter Property="Background" Value="White"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type TextBox}"> <Border Margin="6,2,0,4" BorderBrush="#FFBDBEBD" BorderThickness="1" CornerRadius="8" Background="White" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" MinWidth="100" x:Name="bg"> <ScrollViewer x:Name="PART_ContentHost" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/> </Border> <ControlTemplate.Triggers> <Trigger Property="IsKeyboardFocusWithin" Value="True"> <Setter Property="Background" TargetName="bg" Value="Black"/> <Setter Property="Background" Value="Black"/><!-- we need it for caret, it is black on black elsewise --> <Setter Property="Foreground" Value="White"/> <Setter Property="behave:FocusBehaviour.IsListBoxItemSelected" Value="True"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> 

`

Thirdly. (optional, for the inverse problem)

You will encounter, if not any, inverse problem - focus on the TextBox when choosing ListBoxItem. I recommend using another property of the Behavior class, IsFocused. Here is an example template for ListBoxItem , pay attention to Property="behave:FocusBehaviour.IsFocused" and FocusManager.IsFocusScope="True"

  <DataTemplate x:Key="YourKey" DataType="{x:Type YourType}"> <Border Background="#FFF7F3F7" BorderBrush="#FFBDBEBD" BorderThickness="0,0,0,1" FocusManager.IsFocusScope="True" x:Name="bd" MinHeight="40"> <TextBox x:Name="textBox" Style="{StaticResource PreviewTextBox}" Text="{Binding Value}" /> </Border> <DataTemplate.Triggers> <DataTrigger Binding="{Binding IsSelected,RelativeSource={RelativeSource AncestorType=ListBoxItem}}" Value="True"> <Setter TargetName="textBox" Property="behave:FocusBehaviour.IsFocused" Value="True" /> </DataTrigger> </DataTemplate.Triggers> </DataTemplate> 
+3
Nov 09 '10 at
source share

I use a class handler to set this behavior. Performing this method will eliminate all kinds of lists in the application. I do not know why this is not the default behavior.

In the App.xaml.cs application, add the following to OnStartup:

 protected override void OnStartup(StartupEventArgs e) { EventManager.RegisterClassHandler(typeof (ListViewItem), ListViewItem.PreviewGotKeyboardFocusEvent, new RoutedEventHandler((x,_) => (x as ListViewItem).IsSelected = true)); } 
+3
Jun 16 '11 at 2:01
source share

Is there any property that I need to set for a text field to forward the click event to the list?

This is not just a property, but you can handle the GotFocus event on your TextBox , then use VisualTreeHelper to find the ListBoxItem and select it:

 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; } 
+2
Mar 17 '09 at 16:01
source share

The easiest way I could find this is to use the PreviewMouseDown event and set the IsSelected property of the parent template. Because preview events fail, the ListBoxItem will process the event as soon as the user clicks a text field, combobox, or any other control on which you set the event.

It's good that you can use the same event for all types of controls, since they all come from a Framework element. In addition, installing IsSelected (instead of installing SelectedItem) will result in multiple items being selected if you set the SelectionMode parameter in the "Extended" list, which may or may not be what you are looking for.

t

C # code

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

Xaml

  ... <ComboBox PreviewMouseDown="Element_PreviewMouseDown"/> <TextBox PreviewMouseDown="Element_PreviewMouseDown"/> ... 
+1
Apr 04 '09 at 0:26
source share

this is the answer you are looking for: ListBoxItem selection when its internal ComboBox is focused

+1
Oct 27 '09 at 10:03
source share

The following is a simplification of @Ben's answer without having to override the DataTemplate. It can even be used as a static style. Tested with a ListView containing GridView > GridViewColumn > TextBox .

Example:

 <ListView.Resources> <Style TargetType="{x:Type ListViewItem}"> <Style.Triggers> <Trigger Property="IsKeyboardFocusWithin" Value="True"> <Setter Property="IsSelected" Value="True"></Setter> </Trigger> </Style.Triggers> </Style> </ListView.Resources> 
+1
Jan 31 '17 at 20:50
source share

Listbox handles the selection of items, but is not aware of the focus of the embedded text field. If you want to change the selection when the text field receives input focus, you need to manually change the list selection, afaik.

0
Mar 17 '09 at 9:34
source share

I'm not quite sure that you will want to set the selection directly, as described in the previous answer, because I think it will break the multiselement and some other scenarios

. You might want to try reinstalling the button as shown below and see what happens.

 <Button ClickMode="Pressed" Focusable="False"> <Button.Template> <ControlTemplate> // change the template to get rid of all the default chrome <Border Background="Transparent"> // Button won't be clickable without some kind of background set <ContentPresenter /> </Border> </ControlTemplate> </Button.Template> <TextBox /> 

0
Mar 20 '09 at 16:44
source share

Your not-so-specific information about your initial situation. But I assume that you are using a DataBinding and ItemTemplate. Thats imho an easy way to do this, as well as if your new to this topic. This should work:

 <ListBox ItemsSource="{Binding someDataCollection}" Name="myListBox"> <ListBox.ItemTemplate> <DataTemplate> <TextBox Text="{Binding datafield}" Tag="{Binding .}" GotFocus="TextBox_GotFocus"/> </DataTemplate> </ListBox.ItemTemplate> </ListBox> 



 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) */ } 
0
Mar 26 '09 at 2:03
source share

Try this code:

 foreach (object item in this.listBox1.Items) { if (textbox1.text.equals(item.toString())) { //show error message; break } } 
0
Jun 28 '12 at 6:00
source share

An old discussion, but maybe my answer helps others ...

The Ben solution has the same problem as the Grazer solution. The bad news is that the choice depends on the focus [keyboard] of the text field. If you have other control over your dialog (i.e., Button), the focus is lost when the button is pressed, and listboxitem becomes unselected (SelectedItem == null). So you have a different behavior for clicking on an element (outside the text box) and clicking in the text box. It is very tiring to work and looks very strange.

I am sure there is no pure XAML solution for this. For this we need a code. The solution is close to what Mark suggested.

(in my example, I'm using ListViewItem instead of ListBoxItem, but the solution works for both).

Code for:

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

with FindParent (taken from 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<T>(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<T>(parentObject); } 

In my DataTemplate:

 <TextBox Text="{Binding Name}" PreviewMouseDown="Element_PreviewMouseDown"/> 
0
Jan 08 '15 at 22:02
source share



All Articles