Я озадачен этим:
Я сделал очень простой пример:
MainWindow.xaml:
<Window x:Class="Test.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<Style TargetType="RichTextBox">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="RichTextBox">
<Grid Height="100" Width="200">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Label Background="Blue" Grid.Row="0">Label</Label>
<Border PreviewMouseDown="Border_PreviewMouseDown" Background="Red" Grid.Row="1">
<ScrollViewer x:Name="PART_ContentHost" />
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<RichTextBox>
<FlowDocument>
<FlowDocument.Blocks>
<Paragraph>
oaizeropiazuerpoaizeurpoaizeurpaozieurpaozieru
</Paragraph>
</FlowDocument.Blocks>
</FlowDocument>
</RichTextBox>
</Grid>
</Window>
MainWindow.xaml.cs:
using System.Diagnostics;
using System.Windows;
using System.Windows.Input;
namespace Test
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Border_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
Debug.WriteLine("Click !");
}
}
}
Теперь, когда я явно помещаю PreviewMouseDown EventHandler на Границу, а не на метку в моем шаблоне, я ожидаю, что он будет срабатывать, когда я щелкаю (красную) границу элемента управления, но не когда я нажимаю на (синяя) метка.
Однако событие вызывается, когда я нажимаю (красную) границу И , когда я нажимаю (синюю) метку.
Так почему же Label вызывает EventHandler, который я явно прикрепил к другой части элемента controlTemplate (т.е. границы)?
Я проверил: если я удаляю код PreviewMouseDown="Border_PreviewMouseDown"
из свойств границы, событие больше не вызывается для метки.
что мне здесь не хватает?
а что бы правильно сделать? Как я могу спроектировать свой controlTemplate так, чтобы событие PreviewMouseDown вызывалось только частью элемента шаблонного элемента управления?
заранее спасибо
Редактировать: , следуя ответу Снежного медведя, я проверял исходный источник события, когда нажимал на Метку. Это действительно граница. Почему это так? каким образом граница инкапсулирует метку в шаблоне выше? Я специально установил их на разных строках сетки, чтобы избежать этого, так как получилось?
Edit2 Просто для забавы, я создал обработчик, который печатает только отправителя / source / originalSource события, и прикрепил его в шаблоне к сетке, границе и scrollviewer.
Вот что я получаю, когда нажимаю ОДИН РАЗ (и только один раз) на вертикальной полосе прокрутки, например:
Clic -- Sender: System.Windows.Controls.Grid -- OriginalSource: Microsoft.Windows.Themes.ScrollChrome -- Source: MyRichTextBox
Clic -- Sender: System.Windows.Controls.Border -- OriginalSource: Microsoft.Windows.Themes.ScrollChrome -- Source: MyRichTextBox
Clic -- Sender: System.Windows.Controls.ScrollViewer -- OriginalSource: Microsoft.Windows.Themes.ScrollChrome -- Source: MyRichTextBox
Clic -- Sender: System.Windows.Controls.Grid -- OriginalSource: Microsoft.Windows.Themes.ScrollChrome -- Source: System.Windows.Controls.ScrollViewer
Clic -- Sender: System.Windows.Controls.Border -- OriginalSource: Microsoft.Windows.Themes.ScrollChrome -- Source: System.Windows.Controls.ScrollViewer
Clic -- Sender: System.Windows.Controls.ScrollViewer -- OriginalSource: Microsoft.Windows.Themes.ScrollChrome -- Source: System.Windows.Controls.ScrollViewer
это ясно решает проблему: событие по какой-то причине действительно туннелируется дважды: сначала с TemplatedParent (т.е. RichtextBox) в качестве Source, а затем с contentPresenter (т.е. ScrollViewer) в качестве Source.
Из-за самых мешковатых штанов Мерлина, мне действительно интересно, что произошло через голову MS Dev, который запрограммировал это ...