I have an issue with ListBoxItem
s. 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 Label
s 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
.
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?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With