WPF ListBoxItem ControlTemplate 打破了一些 MouseDown/Selection
WPF ListBoxItem ControlTemplate breaks some MouseDown/Selection
我对 ListBoxItem
有疑问。我也在尝试在 ListBoxItem
select 中制作所有控件,因此单击 TextBox
、Label
等将 select ListBoxItem
.到目前为止很简单。
我也在更改 ListBoxItem
模板以将 selection 可视化从突出显示背景更改为仅绘制边框。也很简单。
然而,这两者的结合似乎会导致 MouseDown
和 PreviewMouseDown
出现一些非常恼人的问题,特别是在我的情况下 [=22= 中的 Label
],其中创建一个 "void" 被 Grid
space.
占用
使用 snoop,我可以看到 PreviewMouseDown
事件在 ListBox
内的 ScrollViewer
停止,并没有一直到 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>
代码隐藏:
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;
}
}
}
但是,如果我删除 Template
setter,一切都很好。我缺少的模板中有什么神奇之处吗?我尝试将边框重命名为 "Bd",因为这是默认模板边框的名称,但没有成功。有什么想法吗?
如果您将标签的水平对齐方式从 "Left" 更改为 "Stretch",这将解决问题并保持视觉格式不变。
鼠标按下事件仅在元素存在的区域有效。通过使标签处于 "left" 水平对齐,您正在创建您提到的 "void",其中在该级别不存在可以单击的元素。要直观地看到差异,请尝试暂时设置给您带来问题的标签元素的背景 属性,您会发现该元素不会一直延伸到文本框。
我对 ListBoxItem
有疑问。我也在尝试在 ListBoxItem
select 中制作所有控件,因此单击 TextBox
、Label
等将 select ListBoxItem
.到目前为止很简单。
我也在更改 ListBoxItem
模板以将 selection 可视化从突出显示背景更改为仅绘制边框。也很简单。
然而,这两者的结合似乎会导致 MouseDown
和 PreviewMouseDown
出现一些非常恼人的问题,特别是在我的情况下 [=22= 中的 Label
],其中创建一个 "void" 被 Grid
space.
使用 snoop,我可以看到 PreviewMouseDown
事件在 ListBox
内的 ScrollViewer
停止,并没有一直到 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>
代码隐藏:
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;
}
}
}
但是,如果我删除 Template
setter,一切都很好。我缺少的模板中有什么神奇之处吗?我尝试将边框重命名为 "Bd",因为这是默认模板边框的名称,但没有成功。有什么想法吗?
如果您将标签的水平对齐方式从 "Left" 更改为 "Stretch",这将解决问题并保持视觉格式不变。
鼠标按下事件仅在元素存在的区域有效。通过使标签处于 "left" 水平对齐,您正在创建您提到的 "void",其中在该级别不存在可以单击的元素。要直观地看到差异,请尝试暂时设置给您带来问题的标签元素的背景 属性,您会发现该元素不会一直延伸到文本框。