2011-04-08 35 views
4

我想動態填充各種MenuItems(全部在代碼中創建)的菜單控件(它駐留在ControlTemplate中),但我遇到了一些奇怪的問題。如果MenuItems全部作爲根項目創建,則它們成功觸發其Click事件。但是,只要有任何MenuItem成爲另一個MenuItem的子項,則父項和子項的Click事件都將停止觸發。WPF MenuItem.Click育兒後休息

XAML:

<ControlTemplate> 
    <Menu x:Name="MyMenu"/> 
</ControlTemplate> 

C#:

// This is in the control that the above ControlTemplate is created for 
public override void OnApplyTemplate() 
{ 
    base.OnApplyTemplate(); 

    MenuItem L1 = new MenuItem() { Header = "L1" }; 
    MyMenu.Items.Add(L1); // Add as root 
    L1.Click += new RoutedEventHandler(delegate { MessageBox.Show("L1 Click"); }); 

    MenuItem L2 = new MenuItem() { Header = "L2" }; 
    L1.Items.Add(L2); // Add as child of L1. 
    // Note: If this is a child of MyMenu, both MenuItems work as expected 
    L2.Click += new RoutedEventHandler(delegate { MessageBox.Show("L2 Click"); }); 
} 

菜單顯示正確,但沒有對分項火災所有的點擊事件。如果我在XAML中預先定義了菜單並在XAML中設置了所有的Click事件,那麼它可以很好地工作 - 但它必須在代碼中,所以這不是一個選項。另外,如果我讓'L2'成爲'MyMenu'的一個孩子,也就是使它成爲一個根項目,L1和L2開始重新工作 - 但我不能將所有東西都作爲根項目。 有什麼,我失蹤?

謝謝!

編輯1:

我已經嘗試做一些實驗,看看是否一切都爲人父母的L1至L2,增加他們的Click事件之前正確初始化。仍然沒有運氣。這裏是我的嘗試:

XAML:

<ControlTemplate> 
    <Grid> 
     <Menu x:Name="MyMenu"/> 
     <Button x:Name="MyButton"/> 
    </Grid> 
</ControlTemplate> 

C#:

public override void OnApplyTemplate() 
{ 
    base.OnApplyTemplate(); 

    MenuItem L1 = new MenuItem() { Header = "L1" }; 
    MyMenu.Items.Add(L1); 

    MenuItem L2 = new MenuItem() { Header = "L2" }; 
    MyMenu.Items.Add(L2); // Add this to the menu to make sure it gets initialised 

    // I created a button so I can make sure that the parenting 
    // and events are only added after the MenuItems are loaded 
    MyButton.Click += new RoutedEventHandler(MyButton_Clicked); 
} 

void MyButton_Clicked(object sender, RoutedEventArgs e) 
{ 
    // Note: If these two lines are removed, the events work fine 
    MyMenu.Items.Remove(L2); 
    L1.Items.Add(L2); 

    L1.Click += new RoutedEventHandler(delegate { MessageBox.Show("L1 Click"); }); 
    L2.Click += new RoutedEventHandler(delegate { MessageBox.Show("L2 Click"); }); 
} 

當窗口負載,一切都顯示,我點擊按鈕,這樣的養育情況和事件被添加。我看到L2正在作爲L1的一個孩子移動,但是當我點擊其中一個時,他們不會響應Click事件。如果我阻止父母表單發生,他們確實會對Click事件做出響應。我很困惑,爲什麼會發生這種情況!

編輯2:

我複製一切從原來的職位在一個乾淨的項目,而這一切完美的作品。所以這不是菜單或菜單項或使用方式的問題。這個問題的原因仍是未知數......

編輯3:

按照要求,我重新測試該用下面的代碼添加到窗口:

PreviewMouseLeftButtonDown += new MouseButtonEventHandler(delegate 
{ 
    // Use Ctrl key to enable MessageBox so focus is not lost when opening menu 
    if (Keyboard.Modifiers == ModifierKeys.Control) 
     MessageBox.Show("Window PreviewMouseLeftButtonDown"); 
}); 

的PreviewMouseLeftButtonDown始終觸發當按Ctrl-點擊'死'MenuItems。他們的Click事件在成爲父母后繼續停止工作。仍然沒有解決,也沒有問題的指示...

EDIT 4:

我做了以下測試,加入下面的代碼兩者L1和L2:

L1.PreviewMouseLeftButtonDown += new MouseButtonEventHandler(delegate 
{ 
    MessageBox.Show("L1 PreviewMouseLeftButtonDown"); 
}); 
// Same for L2 

單擊時,菜單項L1和L2都會對PreviewMouseLeftButtonDown作出響應,但在成爲父對象後繼續停止響應Click。

+0

如果你先建立你的整個菜單樹,然後把'L1'附加到'MyMenu.Items',它會起作用嗎? – Rachel 2011-04-08 15:24:02

+0

不,它仍然不起作用。作爲一個實驗,我創建了一個帶有Click事件的Button,它將L2設置爲L1的子項,然後爲這兩個MenuItem設置Click事件。這是爲了保證在添加父母和處理程序時,這些菜單項完全加載。一旦發生任何親子關係,這兩個事件就會停止。 – Riaan 2011-04-08 22:20:50

+0

只是爲了確保你不會瘋狂,你有沒有嘗試附加一個處理程序的窗口的[PreviewMouseLeftButtonDown](http://msdn.microsoft.com/en-us/library/system.windows.uielement.previewmouseleftbuttondown.aspx )事件來查看是否有什麼東西在冒泡? – 2011-04-09 00:57:13

回答

2

我終於解開了這個謎。儘管奇怪的是,菜單保持打開狀態並對導航做出反應,儘管它沒有焦點,但我在父控制中竊取焦點後發現了問題。一切似乎與調用焦點()被刪除。

發生了什麼事情的細節:

WITHOUT菜單項育兒:

1)我點擊一個菜單項根,它響應點擊。

2)OnPreviewMouseDown然後被父母攔截並調用Focus()。

由於Click已成功解僱,因此在此情況下失去焦點造成不良後果。

菜單項育兒:

1)我在菜單上單擊它打開。

2)OnPreviewMouseDown然後被父母攔截並調用Focus()。

3)菜單保持打開並繼續對導航做出反應(這是否意味着會發生?)。

4)當我點擊任何MenuItem上的第二次進行選擇時,菜單最終意識到它失去了焦點並關閉 - 也放棄了點擊。

然後它似乎像一個點擊是由MenuItem做出並拋棄...導致原來的帖子經歷的問題。