Hopefully a simple question as I'm just getting to grips with routed events.

I have a custom UserControl. This contains lots of other controls.

Further up my tree I want to respond to double click events originating from one of the contained controls (not my UserControl). However, my UserControl is obviously catching the event and setting the source property to itself. How can I stop it doing this?

I cannot use OriginalSource since this points to the lowest level control clicked (Border or whatever).

eg.

MyWindow <--- Want to handle double click here with Source = MyContainedControl1
 |
 +-MyUserControl (this is setting Source to itself. How do I turn this off?)
    |
    +-MyContainedControl1 
       |
       Border    <---- Mouse double clicks here
       EditBox
       Etc

I have tried overriding OnMouseDoubleClick() and OnPreviewMouseDoubleClick() in MyUserControl, but at this point the events already have the Source set to MyUserControl even before calling base or anything.

Many thanks

有帮助吗?

解决方案 3

I've managed to fix it by changing my UserControl to a ContentControl instead. Luckily my content is all dynamically loaded at runtime, so I don't need the design time surface that UserControl provides. Despite much searching I couldn't find anything about the UserControl effects on events, other than one sentence within WPF Unleashed (page 722)

That’s because UserControl differs very little from its ContentControl base class; it has a different default control template, it has a default content alignment of Stretch in both directions (rather than Left and Top), it sets IsTabStop and Focusable to false by default, and it changes the source of any events raised from inner content to be the UserControl itself.

I also had to change to using PreviewMouseDown rather than MouseDoubleClick, since MouseDoubleClick is not a real bubbling event. See Control.MouseDoubleClick:

Although this routed event seems to follow a bubbling route through an element tree, it actually is a direct routed event that is raised along the element tree by each UIElement.

If I had needed the UserControl, then I think I'd have had to do as Klaus78 suggests and raise my own custom event in ContainedControl, or subscribe to the double click events on each ContainedControl manually rather than letting them bubble up.

其他提示

I'd just walk the visual tree like so:

        private void Window_PreviewMouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            var control = FindVisualParent<MyContainedControl1>(e.OriginalSource as DependencyObject);
            if (control != null)
            {
                //magic happens here
            }
        }

        public static T FindVisualParent<T>(DependencyObject child) where T : DependencyObject
        {
            var parent = VisualTreeHelper.GetParent(child);
            if (parent == null) 
                return null;
            T pT = parent as T;
            return pT != null ? pT : FindVisualParent<T>(parent);
        }

May be you can try changing your RoutingStrategy.

http://msdn.microsoft.com/en-us/library/system.windows.routingstrategy.aspx

you can use jquery event.preventDefault() API for this.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top