I Have a wpf Listbox that display\'s a list of textboxes. When I click on the Textbox the Listbox selection does not change. I have to click next to the TextBox to select th
I'm not entirely sure you would want to set the selection directly as described in the previous answer because I think it would break multiselection and some other scenerios
. You might want to try restyling a button like 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 />
The Listbox handles item selection but does not know about focus of the textbox embedded within. If you want to change the selection whenever a textbox gets input focus then you need to change the listbox selection manually, afaik.
Your not very specific about your initial situation. But i assume that you use DataBinding and an ItemTemplate. Thats imho an easy way to do this, as well if your beginner on 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) */
}
We use the following style to set a PreviewGotKeyboardFocus which handles all events of TextBox control and ComboBoxes and such:
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<EventSetter Event="PreviewGotKeyboardFocus" Handler="SelectCurrentItem"/>
</Style>
</ListView.ItemContainerStyle>
And then we select the row in code behind:
protected void SelectCurrentItem(object sender, KeyboardFocusChangedEventArgs e)
{
ListViewItem item = (ListViewItem) sender;
item.IsSelected = true;
}
I don't have enough reps to comment, so I am posting my comment as answer. Grazer's solution above does not work in cases where you have another control such as a Button
that needs the SelectedItem
. This is because as per the Style Trigger
, the IsKeyboardFocusWithin
becomes false when you click on that Button
, and the SelectedItem
becomes null.
Attached behavior based on Arcturus Answer to make it reuseable and to have it not hidden in the code behind.
public static class SelectListBoxItemWhenControlInsideTheItemIsClickedBehavior
{
public static readonly DependencyProperty EnableProperty = DependencyProperty.RegisterAttached(
"Enable",
typeof(bool),
typeof(SelectListBoxItemWhenControlInsideTheItemIsClickedBehavior),
new FrameworkPropertyMetadata(false, OnEnableChanged));
public static bool GetEnable(FrameworkElement frameworkElement)
{
return (bool)frameworkElement.GetValue(EnableProperty);
}
public static void SetEnable(FrameworkElement frameworkElement, bool value)
{
frameworkElement.SetValue(EnableProperty, value);
}
private static void OnEnableChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if ( d is ListBoxItem listBoxItem)
listBoxItem.PreviewGotKeyboardFocus += ListBoxItem_PreviewGotKeyboardFocus;
}
private static void ListBoxItem_PreviewGotKeyboardFocus(object sender, System.Windows.Input.KeyboardFocusChangedEventArgs e)
{
var listBoxItem = (ListBoxItem)sender;
listBoxItem.IsSelected = true;
}
}
For example <Windows.Resources>
<Window.Resources>
<Style TargetType="ListViewItem">
<Setter Property="myBehavior:SelectListBoxItemWhenControlInsideTheItemIsClickedBehavior.Enable" Value="true"/>
</Style>
</Window.Resources>
if visual studio is not clever enough to add it automatically. for example when your project is called "MyApp" and you saved the file in the Folder "MyBehaviors", the Namespace would be under Window:
<Window
xmlns:myBehavior="clr-namespace:MyApp.MyBehaviors"
>