Auto-Select First Item Using XAML for Selector-Derived Controls (ListBox, ListView, TabControl, etc)


Problem

When your application has a control on it that derives from Selector and has no items on load nothing is selected. During run-time when the user is clicking around and adds items to the Selector-derived control, you would assume that the control would automatically select the first item because that only makes sense. However, your assumption and mine would be wrong; this is not the behavior at all. Instead the selector will still have no items selected. This means in order to get this “auto-select first item” behavior, you have to do it yourself. Luckily its an easy fix as shown below.

Solution

<Style x:Key="SelectorAutoSelectStyle"
       TargetType="{x:Type Selector}">
    <Style.Triggers>
        <MultiTrigger>
            <MultiTrigger.Conditions>
                <Condition Property="SelectedItem"
                           Value="{x:Null}" />
                <Condition Property="HasItems"
                           Value="True" />
            </MultiTrigger.Conditions>
            <Setter Property="SelectedIndex"
                    Value="0" />
        </MultiTrigger>
    </Style.Triggers>
</Style>

<Style BasedOn="{StaticResource SelectorAutoSelectStyle}"
       TargetType="{x:Type ListBox}" />

<Style BasedOn="{StaticResource SelectorAutoSelectStyle}"
       TargetType="{x:Type ListView}" />

<Style BasedOn="{StaticResource SelectorAutoSelectStyle}"
       TargetType="{x:Type TabControl}" />

Since the auto-select behavior is in the base style for the base Selector class, derived classes, and therefore styles, can inherit this behavior. When you have a Selector-derived class (ListBox, ListView, TabControl, etc) and you want to apply the auto-select behavior to it’s style, all you need to do is set the style’s BasedOn property to SelectorAutoSelectedStyle and you’re good to go!

So there you have it, and if you find a better solution be sure to add a comment to this post.

, , , , , ,

  1. #1 by Anonymous on May 5, 2016 - 10:24 pm

    This doesn’t work….and I don’t see how it could work “HasItems” is not a Dependency Property.

  2. #2 by Anonymous on December 18, 2014 - 3:50 am

    when I use tabcontrol’s itemsource to generate the tabitems,(cascade tablecontrol ,such as home1->parent->childern,home2->parent->children), the style will throw an out of index exception.

  3. #3 by huoxudong125 on December 17, 2014 - 9:30 pm

    Reblogged this on ITelite.

  4. #4 by Anonymous on October 23, 2013 - 10:58 pm

    how to select last item added in the list?

    • #5 by Tim Valentine on October 26, 2013 - 1:28 pm

      Selecting the last item would be more complicated. You could bind SelectedIndex to Items.Count with a binding mode of OneWay. But Count is one higher than the highest index, so you’d be off by one. You’d need a valueconverter to subtract one from count.

      Another approach could be calling MoveCurrentToLast() method on Items since it inherits from CollectionView. You’d need to play with a ObjectDataProvider to make the call. This would be the only pure XAML approach I can think of.

      Third approach would just be creating an attached property on Selector called AutoSelectLastItemOnLoad or something. And do you’re work in there, research attached properties for that.

  5. #6 by Carlos on May 16, 2011 - 7:29 am

    Very ingenious, Thanks!

  6. #7 by Anonymous on December 30, 2010 - 4:47 am

    Thanks!
    This is the most elegant solution I’ve seen!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: