Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF ListBoxItem ControlTemplate breaks some MouseDown/Selection

Tags:

c#

wpf

listbox

I have an issue with ListBoxItems. I am trying to make all controls in the ListBoxItem select it as well, so clicking on a TextBox, Label, etc will select the ListBoxItem. Pretty simple so far.

I am also changing the ListBoxItem Template to change the selection visualization from highlighting the background to just drawing a border. Also pretty simple.

The combination of these two, however, seems to cause some really irritating issues with MouseDown and PreviewMouseDown, specifically in my case regarding Labels in a Grid, where one creates a "void" occupied by Grid space.

Using snoop, I can see the PreviewMouseDown event stopping at the ScrollViewer inside the ListBox, and not going all the way to the ListBoxItem.

click no worky

XAML:

<Window x:Class="ListBoxClickThroughTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow"
        Width="525"
        Height="350">
    <Grid>
        <ListBox ItemsSource="{Binding Items}"
                 SelectionMode="Single">

            <ListBox.ItemTemplate>
                <DataTemplate>
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="Auto" />
                            <ColumnDefinition Width="*" />
                        </Grid.ColumnDefinitions>
                        <Grid.RowDefinitions>
                            <RowDefinition />
                            <RowDefinition />
                        </Grid.RowDefinitions>

                        <Label Name="VerySuperLongLabel"
                               Grid.Row="0"
                               Grid.Column="0"
                               HorizontalAlignment="Left"
                               Content="VerySuperLongLabel"
                               Padding="0" />

                        <TextBox Name="Textbox1"
                                 Grid.Row="0"
                                 Grid.Column="1"
                                 HorizontalAlignment="Stretch"
                                 HorizontalContentAlignment="Right"
                                 Text="Textbox1 Text" />


                        <Label Name="ShortLabel"
                               Grid.Row="1"
                               Grid.Column="0"
                               HorizontalAlignment="Left"
                               Content="ShortLabel"
                               Padding="0" />
                        <TextBox Name="Textbox2"
                                 Grid.Row="1"
                                 Grid.Column="1"
                                 HorizontalAlignment="Stretch"
                                 HorizontalContentAlignment="Right"
                                 Text="Textbox2 Text" />
                    </Grid>
                </DataTemplate>
            </ListBox.ItemTemplate>

            <ListBox.ItemContainerStyle>
                <Style TargetType="{x:Type ListBoxItem}">
                    <EventSetter Event="PreviewMouseDown"
                                 Handler="ListBoxItem_PreviewMouseDown" />
                    <EventSetter Event="MouseDown"
                                 Handler="ListBoxItem_PreviewMouseDown" />
                    <Setter Property="HorizontalContentAlignment" Value="Stretch" />
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="{x:Type ListBoxItem}">
                                <Border x:Name="Bd"
                                        BorderThickness="1">
                                    <ContentPresenter />
                                </Border>
                                <ControlTemplate.Triggers>
                                    <Trigger Property="IsSelected" Value="true">
                                        <Setter TargetName="Bd" Property="BorderBrush" Value="Gray" />
                                    </Trigger>
                                </ControlTemplate.Triggers>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </ListBox.ItemContainerStyle>
        </ListBox>

    </Grid>
</Window>

Code-behind:

using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

namespace ListBoxClickThroughTest
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            Items = new List<string>() { "1", "2" };
            InitializeComponent();
            DataContext = this;
        }

        public List<string> Items { get; set; }

        private void ListBoxItem_PreviewMouseDown(object sender, MouseButtonEventArgs e)
        {
            var listBoxItem = (ListBoxItem)sender;
            listBoxItem.IsSelected = true;
        }
    }
}

However, if I remove the Template setter, all is well. Is there some magic in the template I'm missing? I tried renaming the border to "Bd" as that was what the default template border was named, but no luck. Any ideas?

like image 986
Isaac Baker Avatar asked Jun 08 '15 17:06

Isaac Baker


1 Answers

If you change the horizontal alignment of the labels from "Left" to "Stretch" this will fix the problem and keep the visual formatting the same.

Mousedown events only work in areas where elements exist. By having the labels at a "left" horizontal alignment, you are creating the "void" you mentioned, where no element exists at that level that can be clicked. To visually see the difference, try temporarily setting the background property of the label elements that are giving you problems, and you'll see the element doesn't extend all the way to the textbox.

like image 86
Aaron Thomas Avatar answered Sep 29 '22 06:09

Aaron Thomas