This is a migrated thread and some comments may be shown as answers.

RadContextMenu and MouseEnter

1 Answer 59 Views
Menu
This is a migrated thread and some comments may be shown as answers.
Jason Edwards
Top achievements
Rank 1
Jason Edwards asked on 02 Nov 2013, 06:19 PM
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;
            }
 
 
 
        }
    }

1 Answer, 1 is accepted

Sort by
0
Rosen Vladimirov
Telerik team
answered on 06 Nov 2013, 09:54 PM
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 >>
Tags
Menu
Asked by
Jason Edwards
Top achievements
Rank 1
Answers by
Rosen Vladimirov
Telerik team
Share this question
or