WPF EventHandler disparó contra el elemento incorrecto

Estoy desconcertado por esto:

He hecho un ejemplo muy simple:

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 !");
      }

   }
}

now, como coloco explícitamente el PreviewMouseDown EventHandler en el borde y no en la etiqueta de mi plantilla, espero que se active cuando hago clic en el borde (rojo) del control, pero no cuando hago clic en el (azul ) etiqueta.

Sin embargo, el evento se dispara cuando hago clic en el borde (rojo) cuando hago clic en la etiqueta (azul).

Entonces por qué la Etiqueta llama a un EventHandler que adjunto explícitamente a otra parte de controlTemplate (es decir, el borde)?

He comprobado: si elimino laPreviewMouseDown="Border_PreviewMouseDown" código de las propiedades del borde, el evento ya no se activa en la etiqueta.

¿que me estoy perdiendo aqui

¿y cuál sería la forma correcta de hacer? ¿Cómo puedo diseñar mi controlTemplate para que el evento PreviewMouseDown se active solo por una subparte del control con plantilla?

gracias por adelantad

Editar siguiendo la respuesta de Snowbear, verifiqué el origen original del evento cuando hago clic en la etiqueta. De hecho es la frontera. ¿Por qué esto es tan? ¿De qué manera el borde encapsula la etiqueta en la plantilla de arriba? Los configuré específicamente en diferentes filas de cuadrícula para evitar esto, entonces, ¿cómo es posible?

Edit2 Solo por diversión, creé un controlador que solo imprime el remitente / fuente / fuente original del evento, y lo adjunté en la plantilla a La cuadrícula, el borde y el visor de desplazamiento.

Esto es lo que obtengo cuando hago clic UNA VEZ (y solo una vez) en la barra de desplazamiento vertical, por ejemplo:

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

esto claramente resuelve el asunto: el evento se hace un túnel dos veces, por alguna razón, primero con el TemplatedParent (es decir, el RichtextBox) como Fuente, y luego con el ContentPresenter (es decir, el ScrollViewer) como Fuente.

Por los pantalones más anchos de Merlín, realmente me pregunto qué pasó por la cabeza del MS Dev que programó esto ...

Respuestas a la pregunta(2)

Solución de preguntas

Gee, has descubierto un comportamiento muy extraño. Parece que el manejo del mouse para todos los elementos que forman parte de unaTextBoxBasea plantilla @ control se puede reflejar en el elemento de contenido de texto y luego hacer un túnel / burbuja desde allí. Como resultado, incluir una etiqueta en una plantilla de control de cuadro de texto enriquecido significa que participará en eventos del mouse en el texto enriquecido como si fuera parte del texto enriquecido en sí mismo.

ara solucionar este problema, puede usar unContentControl que incluye los elementos asociados y luego reenvía suContent propiedad de un @ "normal&quoTextBoxBase elemento derivado. Aquí hay un ejemplo simplificado de XAML. La primera sección reproduce el comportamiento extraño en un ejemplo más simple y la segunda sección muestra cómo usar unaContentControl para solucionar el problema.

<Grid>
    <StackPanel>
        <TextBox Text="Some text">
            <TextBox.Template>
                <ControlTemplate TargetType="TextBox">
                    <StackPanel>
                        <Rectangle Fill="Green" Width="200" Height="50"/>
                        <Border x:Name="RedBorder" PreviewMouseDown="Border_PreviewMouseDown" Background="Red">
                            <AdornerDecorator x:Name="PART_ContentHost" />
                        </Border>
                    </StackPanel>
                </ControlTemplate>
            </TextBox.Template>
        </TextBox>
        <ContentControl Content="Some text">
            <ContentControl.Template>
                <ControlTemplate TargetType="ContentControl">
                    <StackPanel>
                        <Rectangle Fill="Green" Width="200" Height="50"/>
                        <Border x:Name="RedBorder" PreviewMouseDown="Border_PreviewMouseDown" Background="Red">
                            <TextBlock Text="{TemplateBinding Content}"/>
                        </Border>
                    </StackPanel>
                </ControlTemplate>
            </ContentControl.Template>
        </ContentControl>
    </StackPanel>
</Grid>
 David18 feb. 2011 09:08
gracias por la sugerencia de usar un ControlTemplate. Marqué esto como la mejor respuesta. Creo que iré por un UserControl de esta manera. Y completé un informe de error en MS connect, ya que no puedo ver cómo esto podría comportarse de esta manera (quién sabe, tal vez MS no ignore este ...)

Te estás perdiendo eventos burbujeantes aquí. @http: //msdn.microsoft.com/en-us/library/ms742806.aspx#routing_strategie

Puedes comprobarRoutedEventArgs.OriginalSource para determinar en qué borde se hizo clic.

ACTUALIZA: Ok, parece que me perdí, pero no del todo. He jugado durante algún tiempo con tu muestra, parece queRichTextBox (o probablementeTextBoxBase) hace algo conPART_ContentHost que obliga atunnelling eventos para ir hacia esta parte. Su muestra se comporta bien con RichTe, xtBox, por lo que supongo que hace algo con su propia plantilla. Aunque no sé cómo investigarlo más a fondo sin consultar las fuentes .Net.

 David17 feb. 2011 15:04
"Burbujeo: se invocan los controladores de eventos en el origen del evento. El evento enrutado luego se enruta a elementos primarios sucesivos hasta llegar a la raíz del árbol de elementos" <La etiqueta no es padre del borde de ninguna manera, entonces, ¿por qué el evento burbujearía? el borde de la etiqueta? Entiendo por qué aparece en el RichTextBox, que es el padre con plantilla, pero ¿cómo es que la etiqueta es un padre de la frontera aquí?
 David17 feb. 2011 15:09
Edité mi pregunta con respecto a su respuesta. Creo que estás en el camino correcto, pero esto aún no explica todo (ver la edición)
 Snowbear17 feb. 2011 15:44
@ David, actualizado.
 David17 feb. 2011 16:01
Estoy de acuerdo con tu edición. Realmente me gustaría saber qué está pasando y cómo puedo hacer que esta maldita plantilla funcione como se supone ...: /

Su respuesta a la pregunta