2

Looking at the following picture you see that the TextBox in the fourth ListBoxItem has the Focus and KeyboardFocus while the second ListBoxItem is selected.

I know I can catch the GotFocus event of the Textbox, grab its DataContext, and set the IsSelected property of the bound object so the ListBoxItem becomes selected.

I'm wondering if it's possible to get the ListBoxItem selected when a user clicks any of the controls it contains? I'm asking this because I have a somewhat elaborate TreeView with a bunch of controls, and I'm looking for a simple or elegant way of having a TreeViewItem selected whenever the user clicks anywhere on it.

enter image description here

UPDATE:

I accepted Rachel's answer as it works perfectly with a ListBox, and it guided me to a solution that seems to be holding up for my TreeView: listen for the GotFocus event on TreeViewItems, and when the event occurs, set e.Handled to true to prevent the event from bubbling up to ancestors of the now selected TreeViewItem

Xaml:

<TreeView>
    <TreeView.Resources>
        <Style TargetType="TreeViewItem">
            <EventSetter Event="GotFocus" Handler="TVI_GotFocus"/>
            ...

C#:

    void TVI_GotFocus(object sender, RoutedEventArgs e)
    {
        e.Handled = true;
        if (!(sender is TreeViewItem))
            return;
        if (((TreeViewItem)sender).IsSelected)
            return;
        ((TreeViewItem)sender).IsSelected = true;
    }

2 Answers2

2

You should also be able to setup a trigger against ListBoxItem.IsKeyboardFocusWithin and avoid any code behind:

<Style TargetType="ListBoxItem">
  <Style.Triggers>
    <Trigger Property="IsKeyboardFocusWithin" Value="True">
      <Setter Property="IsSelected" Value="True" />
    </Trigger>
  </Style.Triggers>
</Style>
sellmeadog
  • 7,437
  • 1
  • 31
  • 45
  • 1
    This only keeps the item selected as long as it has Keyboard Focus. If you remove keyboard focus, such as clicking a button or TextBox outside the Listbox, the item becomes unselected again. I used to use this until I noticed that :) – Rachel Aug 05 '11 at 12:25
  • A similar approach that keeps the selection can be found here [http://stackoverflow.com/a/7555852/1774011](http://stackoverflow.com/a/7555852/1774011) – chriga Nov 28 '13 at 11:15
1

Put this in your ListBox.Resources

<Style TargetType="{x:Type ListBoxItem}">
    <EventSetter Event="PreviewGotKeyboardFocus" Handler="SelectCurrentItem"/>
</Style>

And this in the Code Behind

protected void SelectCurrentItem(object sender, KeyboardFocusChangedEventArgs e)
{
    ListBoxItem item = (ListBoxItem)sender;
    item.IsSelected = true;
}
Rachel
  • 130,264
  • 66
  • 304
  • 490
  • Hi Rachel. I've seen several of your other posts on SO. I'm trying to find a solution to this where it contains no code-behind as I'm doing pure MVVM (no code behind at all). The **IsKeyboardFocusWithin** solution won't work since I always want the selected item to remain selected, even if the ListBox loses focus. Any ideas? – Michael Yanni Jan 04 '13 at 20:09
  • 3
    @MichaelYanni You can either create an `IsSelected` property on your data item, and bind `ListBoxItem.IsSelected` to it, or store a `SelectedItem` or `SelectedIndex` property in your data context,and bind `ListBox.SelectedItem` or `ListBox.SelectedIndex` to it. But don't forget MVVM doesn't mean "no code behind", it means "no business or application logic in code behind". It's perfectly fine to have view-specific code in the code-behind when using MVVM – Rachel Jan 05 '13 at 16:14