可能我还没有真正了解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"));
}
}
答案 0 :(得分:0)
你所面对的是event routing in WPF。要防止事件被路由到下一级别,您必须设置Handled = true
。您还可以检查引发此事件的发件人类型,以过滤掉不必要的呼叫。
private void TabItem_MouseLeftButtonDownEvent(object sender, RoutedEventArgs e)
{
this.IsSelected = true;
e.Handled = true;
}
在用户输入(from MSDN)时,有一个非常好的图表显示事件路由:
因此,要获得所需的 bottom-&gt; up 路由路径,您需要使用Bubble
将行为更改为Tunnel
而不是PreviewLeftMouseButtonDown
。