7

これは私のコントロール ツリーがどのように見えるかです:

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

マウス ホイールを使用すると、コントロールは自動的に親から子のスクロール ビューアーに渡されますが、子のスクロール ビューアーの最後までスクロールすると、コントロールは親のスクロール ビューアーに戻りません。どうすればこれを達成できますか?

エキスパンダー、グリッド、スクロールビューアーは動的に生成されます。

4

2 に答える 2

11

私のアプリケーションでも同様の問題が発生します。イベントをキャッチして親にも渡す依存プロパティによって修正します。これは、スクロールを含むすべてのコントロールに適用できます。しかし、私にとっては、スクロールの最後に彼の親に送るかどうかを検証する必要はありませんでした。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);
   }
}
于 2012-08-22T19:48:23.587 に答える
1

ジャニックの答えや他のいくつかに触発されて、内部のもの(ListView、ListBox、DataGridを含む)が上/下をスクロールするときに祖先のScrollViewerをスクロールする実装があります。コードは、非常によく似た質問に対する私の回答にあります。

于 2020-04-15T01:03:24.080 に答える