Пример #1
0
    private static void OnScrollViewerPreviewMouseWheel(object sender, MouseWheelEventArgs e)
    {
        var scrollViewer = sender as ScrollViewer;

        // We only want to process the PreviewMouseWheel event in the following cases:
        // The event was not previously handled
        // The event is a fake event OR the first time we receive an original event
        // The current ScrollViewer was not already processed
        if (!e.Handled && !e.Equals(s_currentOriginalEventArg) && (scrollViewer != null) &&
            (s_sequence == null || (!s_sequence.ScrollViewers.Contains(scrollViewer) && s_sequence.FakeEvents.Contains(e))))
        {
            // Create our fake event that will be used to parse all the children ScrollViewers
            var previewEventArg = new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta)
            {
                RoutedEvent = UIElement.PreviewMouseWheelEvent,
                Source      = e.OriginalSource,
            };

            var originalSource = e.OriginalSource as IInputElement;
            if (originalSource != null)
            {
                if (s_sequence == null)
                {
                    // First time through the sequence, this only happen the first time we receive the original event
                    s_sequence = new ScrollViewerBehaviorSequence(e, scrollViewer, previewEventArg);
                    s_currentOriginalEventArg = e;
                }
                else
                {
                    s_sequence.FakeEvents.Add(previewEventArg);
                    s_sequence.ScrollViewers.Add(scrollViewer);
                }

                // Raise the fake event on the original source, so that it is pushed all the way down the logical tree to all the
                // ScrollViewers (this is done recursively by each child)
                originalSource.RaiseEvent(previewEventArg);

                // Now that all the children ScrollViewers raised their own fake event, we can start going back up the chain
                if (s_sequence.FakeEvents.Contains(e))
                {
                    if (previewEventArg.Handled)
                    {
                        // If one of our children already handled our fake event, handle them all the way up
                        e.Handled = true;
                    }
                    else
                    {
                        // At this point if no one else handled the event in our children, we do our job
                        if (IsScrollSupported(scrollViewer))
                        {
                            // If this ScrollViewer is able to scroll, handle the fake events all the way up
                            e.Handled = true;
                        }

                        if (IsScrollingOutOfBounds(scrollViewer, e.Delta))
                        {
                            // If this ScrollViewer has reached its upper or lower bound, push a MouseWheelEvent on a parent
                            // ScrollViewer that can handle it
                            s_sequence.ForceMouseWheelEvent(scrollViewer, e);
                        }
                    }
                }

                // Remove the current instances of ScrollViewer and fake event from the sequence
                s_sequence.FakeEvents.Remove(previewEventArg);
                s_sequence.ScrollViewers.Remove(scrollViewer);
                if (s_sequence.FakeEvents.Count == 0)
                {
                    s_sequence = null;
                }
            }
        }
    }