我刚加入WPF,当我学习这些 Material 时,遇到了奇怪的问题。

我构建了一个按钮,其中包含带有文本块的图层,并且我想识别用户单击按钮本身的位置(“第一”,“第二”或“第三”)(我输出一条消息)。

除了用户在使用左键(仅用中键或右键)单击时按钮不引发事件之外,其他所有方法都工作正常。

所以我的问题是:为什么当我用鼠标左键按下按钮本身时却没有收到消息框(而我却收到了带有其他鼠标按钮的msg框)?

XAML:

<Button Margin="145,152,144,102" Padding="5,5,5,5" HorizontalAlignment="Center" VerticalAlignment="Center" MouseDown="Button_MouseDown" Height="57" Width="214">
    <WrapPanel>
        <WrapPanel HorizontalAlignment="Center" VerticalAlignment="Center"></WrapPanel>
        <TextBlock Foreground="Black" FontSize="24" MouseDown="TextBlockFirst_MouseDown" >First  </TextBlock>
        <TextBlock Foreground="Red" FontSize="24"   MouseDown="TextBlockSecond_MouseDown">Second </TextBlock>
        <TextBlock Foreground="Blue" FontSize="24"  MouseDown="TextBlockThird_MouseDown" >Third  </TextBlock>
    </WrapPanel>
</Button>

代码:
private void TextBlockFirst_MouseDown(object sender, MouseButtonEventArgs e)
{
    MessageBox.Show("You click on first");
}

private void TextBlockSecond_MouseDown(object sender, MouseButtonEventArgs e)
{
    MessageBox.Show("You click on second");
}

private void TextBlockThird_MouseDown(object sender, MouseButtonEventArgs e)
{
    MessageBox.Show("You click on third");
}

private void Button_MouseDown(object sender, MouseButtonEventArgs e)
{
    // This event not working good
    // only middle & right mouse buttons are recognized
    MessageBox.Show("You click on the button");
}

谢谢!

最佳答案

MouseDown 事件是一个 bubbling event 事件,它从其始发者冒泡到其根父代。但是 Click 事件吞噬了 MouseDown 事件,并且不允许事件冒泡到Button。

您可以使用 PreviewMouseDown 事件,它是一个 tunnelling event ,它从根到其始发者之间建立隧道。因此,button将首先获取此事件,然后获取后续的textBlock。

<Button PreviewMouseDown="Button_MouseDown">
   .......
</Button>

有关清晰的图片,请参见下面的快照:



更新

仅在按钮上挂接PreviewMouseDown事件,并从单个textBlocks中删除处理程序。检查e.OrignialSource以查看TextBlock是实际的原始来源还是按钮。
private void Button_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
    if (!(e.OriginalSource is TextBlock))
    {
        MessageBox.Show("You click on the button");
    }
    else
    {
        switch ((e.OriginalSource as TextBlock).Text)
        {
            case "First":
                MessageBox.Show("You click on first");
                break;
            case "Second":
                MessageBox.Show("You click on second");
                break;
            case "Third":
                MessageBox.Show("You click on third");
                break;
        }
    }
}

XAML
<Button PreviewMouseDown="Button_PreviewMouseDown" Height="57" Width="214">
    <WrapPanel>
        <WrapPanel HorizontalAlignment="Center" VerticalAlignment="Center"/>
        <TextBlock Foreground="Black" FontSize="24">First</TextBlock>
        <TextBlock Foreground="Red" FontSize="24">Second</TextBlock>
        <TextBlock Foreground="Blue" FontSize="24">Third</TextBlock>
    </WrapPanel>
</Button>

09-13 05:00