2010-05-10 81 views
0

我在Silverlight中有一个菜单和子菜单结构,并且当父菜单项失去焦点时我想让子菜单消失 - 标准菜单行为。我注意到当子菜单项被点击时,子菜单的点击事件丢失,因为父菜单项失去焦点并且子菜单消失。按钮单击事件迷失

它很容易与代码解释:

 ParentMenuBtn.Click += delegate 
     { 
      SubMenu.Visibility = (SubMenu.Visibility == Visibility.Visible) ? SubMenu.Collapsed : SubMenu.Visible; 
     }; 
     ParentMenuBtn.LostFocus += delegate 
     { 
      SubMenu.Visibility = Visibility.Collapsed; 
     }; 
     SubMenuBtn.Click += delegate 
     { 
      throw new Exception("This will never be thrown."); 
     }; 

在我的例子,被点击SubMenuBtn时,触发第一个事件是ParentMenuBtn.LostFocus(),隐藏SubMenuBtn的容器。一旦容器的可见性崩溃,就不会触发Click事件。

我宁愿避免隐藏子菜单中的每个时间,但我有点惊讶,Click事件被触发从来没有作为一个结果......

我不能把任何检查在LostFocus()事件中查看SubMenuBtn是否具有焦点,因为直到调用LostFocus()事件之后它才获得焦点。换句话说,当LostFocus()被触发时,SubMenuBtn.IsFocused = false。

任何人对此有任何想法?

回答

0

我已经找到了解决方案 - 尽管它并不像我所希望的那么简单或优雅。解决方案是使用辅助线程,在执行之前只暂停一会儿。

即。

public partial class Navigation : UserControl 
{ 
    public Navigation() 
    { 
     ParentMenuBtn.Click += delegate 
     { 
      SubMenu.Visibility = (SubMenu.Visibility == Visibility.Visible) ? Visibility.Collapsed : Visibility.Visible;  
     }; 
     ParentMenuBtn.LostFocus += delegate(object sender, RoutedEventArgs e) 
     { 
      HideSubMenu(SubMenu); 
     }; 
     SubMenuBtn.Click += delegate 
     { 
      //Sub Menu Button actions... 
     }; 

    private void HideSubMenu(UIElement subMenu) 
    { 
     //Get the Main Page 
     App app = (App)Application.Current; 
     MainPage mainPage = (MainPage)app.RootVisual; 

     Thread thread = new Thread(Navigation.HideSubMenu); 
     thread.Start(new ThreadState(mainPage, subMenu)); 
    } 

    private static void HideSubMenu(object threadStateObj) 
    { 
     ThreadState threadState = (ThreadState)threadStateObj; 
     //Execute after 5 milliseconds... 
     System.Threading.Thread.Sleep(5); 
     threadState.MainPage.Dispatcher.BeginInvoke(delegate() { 
      threadState.TargetElement.Visibility = Visibility.Collapsed; 
     }); 
    } 

我只是用所谓的ThreadState一个简单的对象来处理所有的状态对象我想保留:

public class ThreadState 
{ 
    public MainPage MainPage = null; 
    public UIElement TargetElement = null; 

    public ThreadState(MainPage mainPage, UIElement targetElement) 
    { 
     this.MainPage = mainPage; 
     this.TargetElement = targetElement; 
    } 
}