WPF EventHandler disparado no elemento errado
Estou intrigado com isso:
Eu fiz um exemplo muito simples:
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 !");
}
}
}
agora, como eu coloquei explicitamente o PreviewMouseDown EventHandler na borda e não no rótulo do meu modelo, espero que ele seja acionado quando eu clicar na borda (vermelha) do controle, mas não quando eu clicar na (azul) rótulo.
No entanto, o evento é disparado quando clico na borda (vermelha)E quando clico no rótulo (azul).
então por que o Label chama um EventHandler que eu anexei explicitamente a outra parte do controlTemplate (ou seja, a borda)?
Eu verifiquei: se eu remover oPreviewMouseDown="Border_PreviewMouseDown"
código das propriedades da borda, o evento não é mais disparado no rótulo.
O que estou perdendo aqui?
e qual seria a maneira correta de fazer? Como criar meu controlTemplate para que o evento PreviewMouseDown seja acionado apenas por uma subparte do controle de modelo?
desde já, obrigado
Editar: Após a resposta de Snowbear, verifiquei a origem original do evento quando clico no rótulo. É de fato a fronteira. Porque isto é assim? de que maneira a borda encapsula o rótulo no modelo acima? Eu os defino especificamente em diferentes linhas da grade para evitar isso. Então, como é que é?
Edit2 Apenas por diversão, criei um manipulador que imprime apenas o remetente / origem / origem original do evento e o anexei no modelo à grade, à borda e ao visualizador de rolagem.
Aqui está o que recebo quando clico em UMA VEZ (e apenas uma vez) na barra de rolagem vertical, por exemplo:
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
isso claramente resolve o problema: o evento é realmente tunelizado duas vezes, por algum motivo, primeiro com o TemplatedParent (ou seja: RichtextBox) como origem e, em seguida, com o contentPresenter (ou seja, o ScrollViewer) como origem.
Pelas calças mais largas de Merlin, eu realmente me pergunto o que passou pela cabeça do MS Dev que programou isso ...