2012-05-21 40 views
5

這是我的控件樹是什麼樣子:WPF嵌套Scrollviewers - 讓控制權交還給父母scollviewer

<window> 
<scrollviewer> 
    <expander> 
    <scrollviewer> 
    <grid> 
    </grid> 
    </scrollviewer> 
    </expander> 
    <expander> 
    <scrollviewer> 
    <grid> 
    </grid> 
    </scrollviewer> 
    </expander> 
</scrollviewer> 
</window> 

使用鼠標滾輪,控制自動傳遞從父母到孩子的ScrollViewer,但是當我滾動到孩子scrollviewer的結尾控件不會傳回給父scorllviewer。我如何實現這一目標?

擴展器,網格和scrollviewers是動態生成的。

+0

另請參閱[此問題](http://stackoverflow.com/q/14348517/1925996)的答案。 – piedar

回答

10

我在應用程序中遇到類似的問題。我通過一個依賴性屬性來糾正它,這個屬性將會捕獲並傳遞他的父母的事件。這可以應用於任何有滾動的控件。但對我而言,我不需要驗證它是否在發送給他父母的卷軸末尾。您只需在OnValueChanged方法中添加一個驗證,以確定滾動是在結尾還是在頂部以發送給其父級。

using System.Windows.Controls; 

public static class SendMouseWheelToParent 
{ 
    public static readonly DependencyProperty ScrollProperty 
    = DependencyProperty.RegisterAttached("IsSendingMouseWheelEventToParent", 
     typeof(bool), 
     typeof(SendMouseWheelToParent), 
     new FrameworkPropertyMetadata(OnValueChanged)); 

    /// <summary> 
    /// Gets the IsSendingMouseWheelEventToParent for a given <see cref="TextBox"/>. 
    /// </summary> 
    /// <param name="control"> 
    /// The <see cref="TextBox"/> whose IsSendingMouseWheelEventToParent is to be retrieved. 
    /// </param> 
    /// <returns> 
    /// The IsSendingMouseWheelEventToParent, or <see langword="null"/> 
    /// if no IsSendingMouseWheelEventToParent has been set. 
    /// </returns> 
    public static bool? GetIsSendingMouseWheelEventToParent(Control control) 
    { 
     if (control == null) 
      throw new ArgumentNullException(""); 

     return control.GetValue(ScrollProperty) as bool?; 
    } 

    /// <summary> 
    /// Sets the IsSendingMouseWheelEventToParent for a given <see cref="TextBox"/>. 
    /// </summary> 
    /// <param name="control"> 
    /// The <see cref="TextBox"/> whose IsSendingMouseWheelEventToParent is to be set. 
    /// </param> 
    /// <param name="IsSendingMouseWheelEventToParent"> 
    /// The IsSendingMouseWheelEventToParent to set, or <see langword="null"/> 
    /// to remove any existing IsSendingMouseWheelEventToParent from <paramref name="control"/>. 
    /// </param> 
    public static void SetIsSendingMouseWheelEventToParent(Control control, bool? sendToParent) 
    { 
     if (control == null) 
      throw new ArgumentNullException(""); 

     control.SetValue(ScrollProperty, sendToParent); 
    } 

    private static void OnValueChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e) 
    { 
     var scrollViewer = dependencyObject as Control; 
     bool? IsSendingMouseWheelEventToParent = e.NewValue as bool?; 
     scrollViewer.PreviewMouseWheel -= scrollViewer_PreviewMouseWheel; 

     if (IsSendingMouseWheelEventToParent != null && IsSendingMouseWheelEventToParent != false) 
     { 
     scrollViewer.SetValue(ScrollProperty, IsSendingMouseWheelEventToParent); 
     scrollViewer.PreviewMouseWheel += scrollViewer_PreviewMouseWheel; 
     } 
    } 


    private static void scrollViewer_PreviewMouseWheel(object sender, MouseWheelEventArgs e) 
    { 
     var scrollview = sender as Control; 

     var eventArg = new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta); 
     eventArg.RoutedEvent = UIElement.MouseWheelEvent; 
     eventArg.Source = sender; 
     var parent = scrollview.Parent as UIElement; 
     parent.RaiseEvent(eventArg); 
    } 
} 
+0

我建議使用視覺樹父'VisualTreeHelper.GetParent(scrollview)作爲UIElement;'而不是邏輯樹父'scrollview.Parent作爲UIElement;',但是我不得不承認我不記得那個確實的構造失敗了與合理的父母。 – grek40