Custom WPF and Silverlight ListBox ItemTemplates eat mouse clicks

A WPF or Silverlight ListBox can display anything. By default, it just displays the ToString() of the objects in the ItemsSource, but that can be adjusted. If you want to display a string other than the ToString(), you need to define an ItemTemplate:

<ListBox Height="200" ItemsSource="{Binding Posts}" SelectedItem="{Binding SelectedPost}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <ListBoxItem Content="{Binding Title}"/>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

Unfortunately, when you do this the string eats your mouse clicks. You can click anywhere around the string, but clicking on the string does not select the item.

Here's my solution
Through trial and error (and MSDN) I finally found a solution:

<ListBox Height="200" ItemsSource="{Binding Posts}" SelectedItem="{Binding SelectedPost}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <ListBoxItem IsHitTestVisible="False" Focusable="False" Content="{Binding Title}"/>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

If you set IsHitTestVisible and Focusable both to False on the ListBoxItem, then clicking the text selects the item, just like in the default ToString() scenario. Setting just one or the other does not change the behavior. Both must be changed.

This seems backwards to me. I would expect that you would have to set IsHitTestVisible to False on a TextBlock inside the ListBoxItem, not the ListBoxItem itself. Making the ListBoxItem invisible to hit tests seems like the opposite of what you want to do.

Nevertheless, this works, so I'll add those two attributes from now on. And BTW, my real XAML code uses Update Controls, but I thought I'd show you some Binding code just in case you haven't converted yet.

Update
Here's a simpler solution:

<ListBox Height="200" ItemsSource="{Binding Posts}" SelectedItem="{Binding SelectedPost}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Title}"/>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

It turns out that the content of a ListBox DataTemplate does not have to be a ListBoxItem. There's my old-school Win32 thinking kicking in. If you make it a TextBlock, then it responds correctly to mouse clicks.

Leave a Reply

You must be logged in to post a comment.