How make WPF Listbox child datatemplate controls select the ListBoxItem container when clicked?

2.9k views Asked by At

I have a listbox and in the datatemplate I have an Expander.

If I click on the Expander Header, the expander expand the content zone but not make the parent ListBoxItem Selected.

If I click on the Expanded Content Zone of the Expander, the parent ListBoxItem become selected.

How to make that when clicking the expanderHeader, the content become expanded AND the parent listboxitem become selected?

4

There are 4 answers

0
lonnie On BEST ANSWER

I ran into the same issue and handled it by listening to the PreviewGotKeyboardFocus event on the ListBox. When the focus changes walk the visual tree looking for a ListBoxItem and select it:

    private void ListBox_PreviewGotKeyboardFocus( object sender, KeyboardFocusChangedEventArgs e )
    {
        if( e.NewFocus is FrameworkElement )
        {
            ListBoxItem item = ( e.NewFocus as FrameworkElement ).FindParent<ListBoxItem>();
            if( item != null && !item.IsSelected )
            {
                item.IsSelected = true;
            }
        }
    }

    public static T FindParent<T>( this FrameworkElement element ) where T : FrameworkElement
    {
        DependencyObject current = element;

        while( current != null )
        {
            if( current is T )
            {
                return ( T ) current;
            }

            current = VisualTreeHelper.GetParent( current );
        }

        return null;
    }
0
Bala R On

can't you use the Expanded event for that ?

something like

<Expander Expanded="Expander_Expanded"

and

private void Expander_Expanded(object sender, RoutedEventArgs e)
{
    parentListBox.Focus();
}
1
fixagon On

something you can do is to bind the IsExpanded Property of the Expander directly with the IsSelected Property of the ListBoxItem. But this means, that is you just select an item the expander gets expanded too... And it means too that unselected items are never expanded.

example:

  <ListBox>
    <ListBox.ItemTemplate>
      <DataTemplate>
        <Expander IsExpanded="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}, Path=IsSelected}">
          <TextBlock Text="bla bla" />
        </Expander>
      </DataTemplate>
    </ListBox.ItemTemplate>
    <ListBox.Items>
      <DataObject />
      <DataObject />
    </ListBox.Items>
  </ListBox>
1
Sheridan On

I realise that this question has been answered, but there is a much simpler way to achieve this desired result. You can add a Trigger to the ListBoxItem Style that will select the ListBoxItem whenever an element in its ItemTemplate has keyboard focus:

<Style.Triggers> 
  <Trigger Property="IsKeyboardFocusWithin" Value="True"> 
    <Setter Property="IsSelected" Value="True"/> 
  </Trigger> 
</Style.Triggers>

For more information, view MSDN, or post1 or post2.