Reagieren auf MouseWheel Up and Down

  • WPF MVVM
  • .NET (FX) 4.5–4.8

Es gibt 5 Antworten in diesem Thema. Der letzte Beitrag () ist von kafffee.

    Reagieren auf MouseWheel Up and Down

    Hallo :)

    wie der Titel schon verrät möchte ich auf ein Scrollen des Mausrads über einem Canvas reagieren.

    Am besten alles was vor dem Edit kommt überspringen... :P Hab eine bessere Lösung gefunden...
    __________________________________________________________________________________________
    Jetzt gibt es da ja Folgendes:

    XML-Quellcode

    1. <Canvas Grid.Row="1">
    2. <Canvas.InputBindings>
    3. <MouseBinding MouseAction="WheelClick" Command="{Binding MausRad}"/>
    4. </Canvas.InputBindings>
    5. </Canvas>


    Das wird, anders wie der Name schon sagt, nicht ausgelöst wenn man das MouseWheel klickt, sondern wenn man hoch- oder runterscrollt. Aber das nur nebenbei...
    Das würde ja auch reichen für meine Zwecke, aber es wird leider kein Unterschied gemacht, ob man nun hoch- oder runterscrollt...

    Also hab ich mal gegoogelt, das gab es zwar anscheinend Lösungen, aber die Links waren veraltet. Bis ich dann auf das hier gestossen bin:


    XML-Quellcode

    1. <MouseBinding Gesture="{x:Static me:MouseWheelGesture.CtrlDown}"
    2. Command="me:MainVM.SendBackwardCommand" />

    C#-Quellcode

    1. public class MouseWheelGesture : MouseGesture
    2. {
    3. public MouseWheelGesture() : base(MouseAction.WheelClick)
    4. {
    5. }
    6. public MouseWheelGesture(ModifierKeys modifiers) : base(MouseAction.WheelClick, modifiers)
    7. {
    8. }
    9. public static MouseWheelGesture CtrlDown =>
    10. new(ModifierKeys.Control) { Direction = WheelDirection.Down };
    11. public WheelDirection Direction { get; set; }
    12. public override bool Matches(object targetElement, InputEventArgs inputEventArgs) =>
    13. base.Matches(targetElement, inputEventArgs)
    14. && inputEventArgs is MouseWheelEventArgs args
    15. && Direction switch
    16. {
    17. WheelDirection.None => args.Delta == 0,
    18. WheelDirection.Up => args.Delta > 0,
    19. WheelDirection.Down => args.Delta < 0,
    20. _ => false,
    21. };
    22. }
    23. public enum WheelDirection
    24. {
    25. None,
    26. Up,
    27. Down,
    28. }


    Das scheint mir ja recht einfach zu sein, aber ich bin zu blöd, das in VB zu übersetzen, da das von mir bekannten Onlinekonvertern zum Fehler führt.

    Insbesondere die Doppelpunkte, z.B. in Zeile 1, verwirren mich... Kennt sich jemand bissle damit aus und kann mir sagen, warum die Onlinekonverter nen Fehler bringen?

    Oder hat jemand nen besseren Vorschlag, wie ich in MVVM zwischen Scroll-up and -down vom Mausrad unterscheiden kann?

    _______________________________________________________________________________

    EDIT: Hab doch noch was besseres gefunden, was funktioniert, nur verstehe ich den Code nicht:

    VB.NET-Quellcode

    1. Option Strict On
    2. Imports System.Windows.Input
    3. Namespace mouse
    4. Public Class MouseWheelUp
    5. Inherits MouseGesture
    6. Public Sub New()
    7. MyBase.New(MouseAction.WheelClick)
    8. End Sub
    9. Public Sub New(ByVal modifiers As ModifierKeys)
    10. MyBase.New(MouseAction.WheelClick, modifiers)
    11. End Sub
    12. Public Overrides Function Matches(ByVal targetElement As Object, ByVal inputEventArgs As InputEventArgs) As Boolean
    13. If Not MyBase.Matches(targetElement, inputEventArgs) Then Return False
    14. If Not (TypeOf inputEventArgs Is MouseWheelEventArgs) Then Return False
    15. Dim args = CType(inputEventArgs, MouseWheelEventArgs)
    16. Return args.Delta > 0
    17. End Function
    18. End Class
    19. End Namespace


    XML-Quellcode

    1. <MouseBinding Command="{Binding MausRad}">
    2. <MouseBinding.Gesture>
    3. <mouse:MouseWheelUp />
    4. </MouseBinding.Gesture>
    5. </MouseBinding>


    Der Command wird nur ausgeführt, wenn man das Rad nach oben dreht... Aber wie gesagt ich verstehe die Klasse MouseWheelUp nicht, so dass ich sie modifizieren könnte... Hat ja offensichtlich was mit den InputEventArgs zu tun...

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „kafffee“ ()

    kafffee schrieb:

    Insbesondere die Doppelpunkte, z.B. in Zeile 1, verwirren mich...


    Ganz einfach

    C#-Quellcode

    1. public class MouseWheelGesture : MouseGesture

    VB.NET-Quellcode

    1. Public Class MouseWheelGesture
    2. Inherits MouseGesture


    Mit dem : base hinter den Konstruktoren ist nicht das gleiche, aber auch leicht zu verstehen, dort wird der entsprechende Konstruktor der beerbten Klasse gecallt. Beim deinem ersten C# Code, also die Konstruktoren der Klasse MouseGesture.

    Ich werde mich auch noch genauer mit Input(Mouse/Touch/Keyboard) auseinander setzen müssen, daher kann ich dazu noch nichts sagen.
    Ja hab das gerade alles gelesen, aber ich kann noch nichts dazu sagen. Ich werde mich damit morgen mal beschäftigen, dann berichten.

    Edit @kafffee

    So wie das gerade einschätze ist die Match funktion zuständig, hier in der Klasse MouseWheelup wird die ja überschrieben. Dort ist zu sehen:

    VB.NET-Quellcode

    1. Return args.Delta > 0

    Was bedeutet MouseWheelUp < 0 wäre dann Down.

    Die Match Funktion ist vergleichbar wie bei den DependencyProperties das ValidateValueCallBack.

    Hier z.B. aus meinem CustomControl, wenn man bei einer int-DependencyProperty nur Werte > 0 und < 11 zulassen will, geben wir der DependencyProperty ein ValidationCallback, die Property wird dann nur geändert, wenn die Bedingung im ValidationCallback zutrifft.

    Auszug aus dem Control:

    C#-Quellcode

    1. public int Zoom
    2. {
    3. get => (int)GetValue(ZoomProperty);
    4. set => SetValue(ZoomProperty, value);
    5. }
    6. public static readonly DependencyProperty ZoomProperty =
    7. DependencyProperty.Register("Zoom", typeof(int), typeof(MyFrameworkElement), new FrameworkPropertyMetadata(2, FrameworkPropertyMetadataOptions.AffectsRender), new ValidateValueCallback(IsZoomInRange));
    8. private static bool IsZoomInRange(object o)
    9. {
    10. return (int)o > 0 && (int)o < 11;
    11. }


    So wie die statische Funktion IsZoomInRange wirkt auch die Funktion "Match", halt nur so das festgestellt werden kann ob rauf/runter. Kopiere diese Klasse nenn sie MouseWheelDown und teste in der Match Funktion auf < 0, sollte dann passen.


    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „BitBrösel“ ()

    Hallo @kafffee

    Du musst es garnicht so kompliziert machen. Dafür gibts von MS ein NuGet Paket um sich solche Behaviours zu holen.

    Hole dir über den Paketmanager Install-Package Microsoft.Xaml.Behaviors.Wpf für dein "View" Projekt

    Dann den Namespace einbinden: xmlns:wi="http://schemas.microsoft.com/xaml/behaviors"

    Und wie folgt binden:

    XML-Quellcode

    1. <Canvas Width="200" Height="200" Background="Green">
    2. <wi:Interaction.Triggers>
    3. <wi:EventTrigger EventName="MouseWheel">
    4. <wi:InvokeCommandAction Command="{Binding TestMouseWeelCommand}" PassEventArgsToCommand="True"/>
    5. </wi:EventTrigger>
    6. </wi:Interaction.Triggers>
    7. </Canvas>


    Der "Clou" hier ist die Eigenschaft PassEventArgsToCommand.
    Das sieht dann so in etwa aus:



    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##