RadContextMenu and MouseEnter

2 posts, 0 answers
  1. Jason Edwards
    Jason Edwards avatar
    1 posts
    Member since:
    Apr 2010

    Posted 02 Nov 2013 Link to this post

    I have a listbox that I am using as a menu bar for a module based app.  Attached to that is a context menu that opens up with subitems based on which listbox item is being hovered over by the mouse.  I am having a couple of problems. What I want is to only have the context menu open if the mouse remains over the item for 1 second.  that way if the user is just scanning over the items the menu won't open.  I have tried setting dispatchertimers along with a mouseleave event like shown here but no luck.  It will work on the first item I go across but then the Opening event never gets fired after that.  I have to move the mouse completely off of the listbox and then back on to get it to work again.  Is what I want even possible or do I need to find a control other than context menu?

    public class NavigatorContextMenu : RadContextMenu
        {
            private bool _isMouseOver = false;
            private bool _hasTimerRun = false;
     
            public NavigatorContextMenu()
                : base()
            {
                Opening += NavigatorContextMenu_Opening;
            }
     
            void NavigatorContextMenu_Opening(object sender, RadRoutedEventArgs e)
            {
                if (_hasTimerRun) return;
                this.ClickedListBoxItem = null;
                this.ClickedListBoxItem = this.GetClickedElement<RadListBoxItem>();
                if (ClickedListBoxItem == null)
                {
                    e.Handled = true;
                    return;
                }
     
                _isMouseOver = true;
                ClickedListBoxItem.MouseLeave += ClickedListBoxItem_MouseLeave;
     
                var timer = new ListBoxItemTimer(((NavItem)ClickedListBoxItem.Content).Label);
                timer.Interval = TimeSpan.FromSeconds(1.5);
                timer.Tick += _timer_Tick;
                e.Handled = true;
                _hasTimerRun = false;
                timer.Start();
            }
     
            void _timer_Tick(object sender, EventArgs e)
            {
                var timer = sender as ListBoxItemTimer;
                timer.Tick -= _timer_Tick;
                timer.Stop();
     
                if (ClickedListBoxItem == null)
                {
                    return;
                }
     
                if (_isMouseOver)
                {
                    _hasTimerRun = true;
                    var navItem = ClickedListBoxItem.Content as NavItem;
     
                    if (navItem == null || navItem.Items == null || navItem.Items.Count <= 0)
                    {
                        return;
                    }
     
                    ClickedListBoxItem.MouseLeave -= ClickedListBoxItem_MouseLeave;
     
                    IsOpen = true;
     
                }
            }
     
            void ClickedListBoxItem_MouseLeave(object sender, MouseEventArgs e)
            {
                ClickedListBoxItem.MouseLeave -= ClickedListBoxItem_MouseLeave;
                _isMouseOver = false;
                _hasTimerRun = false;
            }
     
            public static readonly DependencyProperty ClickedListBoxItemProperty =
                DependencyProperty.Register("ClickedListBoxItem", typeof(RadListBoxItem), typeof(NavigatorContextMenu), new System.Windows.PropertyMetadata(null));
     
            public RadListBoxItem ClickedListBoxItem
            {
                get { return (RadListBoxItem)GetValue(ClickedListBoxItemProperty); }
                set { SetValue(ClickedListBoxItemProperty, value); }
            }
     
            protected override void OnOpened(RadRoutedEventArgs e)
            {
                base.OnOpened(e);
                _hasTimerRun = false;
     
                this.ClickedListBoxItem = null;
                this.ClickedListBoxItem = this.GetClickedElement<RadListBoxItem>();
                if (ClickedListBoxItem == null)
                {
                    e.Handled = true;
                    return;
                }
     
                var navItem = ClickedListBoxItem.Content as NavItem;
     
                if (navItem == null || navItem.Items == null || navItem.Items.Count <= 0)
                {
                    e.Handled = true;
                    return;
                }
     
     
     
            }
        }
  2. Rosen Vladimirov
    Admin
    Rosen Vladimirov avatar
    640 posts

    Posted 06 Nov 2013 Link to this post

    Hello Jason,

    One way to achieve this is to handle RadContextMenu opening on your own by using IsOpen property. For example you can set RadContextMenu's EventName to null and when the DispatcherTimer is completed you can set IsOpen property to true. The only issue with this approach is the position where the context menu will be opened. By default it will be placed below the control on which it is attached. If you want to place it under the mouse you have to handle MouseMove event and get the position from there. 

    I've prepared a sample project that demonstrates this approach. Could you give it a try and inform us in case you have any problems or concerns?

    Regards,
    Rosen Vladimirov
    Telerik
    TRY TELERIK'S NEWEST PRODUCT - EQATEC APPLICATION ANALYTICS for SILVERLIGHT.
    Learn what features your users use (or don't use) in your application. Know your audience. Target it better. Develop wisely.
    Sign up for Free application insights >>
  3. DevCraft banner
Back to Top