父级的事件处理程序从子级捕获事件

时间:2015-02-02 22:06:12

标签: c# wpf events

可能我还没有真正了解WPF中的事件系统。

我有一个TabItem,它有一个由TextBox和Button组成的标题。 TextBox是只读的。 (在真实的应用程序中,它允许双击编辑,但这里无关紧要。

很难选择标签,因为TextBox会抓取MouseLeftButtonDown事件。因此,我向TabItem添加了一个事件处理程序,将其置于前台。但是,使用该事件处理程序,该按钮不再接收该事件。为什么按钮在TabItem获取事件之前没有得到事件?我认为它从叶子到逻辑树的根部起泡。

这是XAML:

<Window x:Class="tt_WPF.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:tt_WPF"
    Title="MainWindow" SizeToContent="WidthAndHeight">
<TabControl x:Name="TC"></TabControl> 
</Window>  

这是背后的代码:

   public class myItem : TabItem
{
    public myItem(string name)
    {
        // Create horizontal StackPanel
        StackPanel sp = new StackPanel();
        sp.Orientation = Orientation.Horizontal;
        // Create a readonly TextBox
        TextBox tb = new TextBox(); 
        tb.Text = name;
        tb.IsReadOnly = true;
        // Create a Button with a simple command
        Button b = new Button();
        b.Content = "X";
        b.Click += Button_Click;
        // Add Button and TextBlock to StackPanel and StackPanel to this TabIten
        sp.Children.Add(tb);
        sp.Children.Add(b);
        this.Header = sp;
        this.Content = "This is " + name;
        // --> Here's the trouble: Install an event handler that brings the TabItem into foreground when clicked
        this.AddHandler(MouseLeftButtonDownEvent, new RoutedEventHandler(TabItem_MouseLeftButtonDownEvent), true);

    }
    private void Button_Click(object sender, RoutedEventArgs e)
    {
        MessageBox.Show("Button X");
    }
    private void TabItem_MouseLeftButtonDownEvent(object sender, RoutedEventArgs e)
    {
        this.IsSelected = true;
    }
}

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        TC.Items.Add(new myItem("Tab 1"));
        TC.Items.Add(new myItem("Tab 2"));
    }
}

1 个答案:

答案 0 :(得分:0)

你所面对的是event routing in WPF。要防止事件被路由到下一级别,您必须设置Handled = true。您还可以检查引发此事件的发件人类型,以过滤掉不必要的呼叫。

private void TabItem_MouseLeftButtonDownEvent(object sender, RoutedEventArgs e)
{
    this.IsSelected = true;
    e.Handled = true;
}

在用户输入(from MSDN)时,有一个非常好的图表显示事件路由:

Events routing

因此,要获得所需的 bottom-&gt; up 路由路径,您需要使用Bubble将行为更改为Tunnel而不是PreviewLeftMouseButtonDown

相关问题