我爲此感到困惑:WPF事件處理髮射了錯誤的元素
我做了一個很簡單的例子:
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放在邊框上,而不是放在模板的標籤上,所以我期望當我點擊控件的(紅色)邊框時會觸發,但當點擊(藍色)標籤時不會觸發。
然而,當我點擊(紅色)邊境事件被觸發和當我點擊(藍色)標籤上。
那麼,爲什麼標籤調用我明確地連接到控件模板(即:邊境)的另一部分的事件處理程序?
我檢查:如果我請從邊框的屬性PreviewMouseDown="Border_PreviewMouseDown"
代碼,該事件不會觸發該標籤的任何更多。
我缺少什麼嗎?
,什麼是做正確的方式?如何設計我的controlTemplate,以便PreviewMouseDown事件僅由模板化控件的子部分觸發?
在此先感謝
編輯:以下Snowbear的回答,我查了事件的originalSource當我點擊標籤。這確實是邊界。這是爲什麼?邊界如何在上面的模板中封裝標籤?我特意將它們放在不同的網格行上以避免這種情況,那麼怎麼來?爲了好玩,我創建了一個處理程序,它只打印事件的sender/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)作爲源,然後與contentPresenter(即:ScrollViewer中)作爲源。
梅林最寬鬆的褲子,我真的不知道通過MS開發的頭編程這...
「鼓泡:事件源上的事件處理程序被調用路由事件然後路由到連續的父元素,直到到達元素樹根」。通過任何手段<標籤是不邊界的父,那麼,爲什麼該事件會爲標籤邊界起泡?我明白爲什麼它會冒泡到RichTextBox,它是模板父類,但標籤在這裏是如何作爲邊界的父項? – David 2011-02-17 14:04:32
我編輯了我的問題關於你的答案。我認爲你是在正確的軌道上,但是這仍然不能解釋一切(見編輯) – David 2011-02-17 14:09:15