Probleme mit ColorAnimation von Path.Fill

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

Es gibt 23 Antworten in diesem Thema. Der letzte Beitrag () ist von DTF.

    Probleme mit ColorAnimation von Path.Fill

    Hallo allerseits :)

    Ich habe Probleme mit dem Animieren der Fill-Eigenschaft eines Path-Controls. Mein Code sieht so aus:

    XML-Quellcode

    1. <Style TargetType="{x:Type Path}">
    2. <Style.Triggers>
    3. <EventTrigger RoutedEvent="MouseLeftButtonDown">
    4. <BeginStoryboard>
    5. <Storyboard>
    6. <ColorAnimation To="White" Duration="00:00:00.500" AutoReverse="True" Storyboard.TargetProperty="(Path.Fill).(SolidColorBrush.Color)"/>
    7. <!--<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Path.Fill).(SolidColorBrush.Color)">
    8. <LinearColorKeyFrame KeyTime="00:00:01" Value="White"/>
    9. </ColorAnimationUsingKeyFrames>-->
    10. </Storyboard>
    11. </BeginStoryboard>
    12. </EventTrigger>
    13. </Style.Triggers>
    14. </Style>


    Ich bekomme die Fehlermeldung:

    ""(0).(1)" kann nicht für eine unveränderliche Objektinstanz animiert werden."

    Aber nur wenn die Instanz von Path so aussieht:

    Spoiler anzeigen

    XML-Quellcode

    1. <Border Name="brdPlay" Grid.Column="2" Style="{DynamicResource Navigationsbuttons}" ToolTip="{Binding PlayToolTip, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}">
    2. <Border.InputBindings>
    3. <MouseBinding MouseAction="LeftClick" Command="{Binding Abspielen}"/>
    4. </Border.InputBindings>
    5. <Canvas Grid.Row="0" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" Width="32" Height="32" VerticalAlignment="Center" HorizontalAlignment="Center">
    6. <Path Name="icoPlay" Fill="{DynamicResource VordergrundfarbeBrush}" Data="{Binding AbspielenIcon, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"/>
    7. </Canvas>
    8. </Border>


    Bei diesen zwei Instanzen von Path funktioniert es:

    Spoiler anzeigen

    XML-Quellcode

    1. <ListBox Name="lstAlben" ScrollViewer.HorizontalScrollBarVisibility="Hidden" Grid.Column="1" Grid.Row="1" ItemsSource="{Binding AnzuzeigendeAlben}" SelectedItem="{Binding AusgewaehltesAlbum, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" SelectionMode="Single" SelectedIndex="{Binding MarkiertesAlbum, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" IsSynchronizedWithCurrentItem="True">
    2. <ListBox.ItemTemplate>
    3. <DataTemplate>
    4. <Grid>
    5. <Grid.ColumnDefinitions>
    6. <ColumnDefinition Width="3*"/>
    7. <ColumnDefinition Width="3*"/>
    8. <ColumnDefinition Width="94*"/>
    9. </Grid.ColumnDefinitions>
    10. <TextBlock Text="{Binding Path=Album}" Grid.Column="2" TextTrimming="CharacterEllipsis">
    11. <ToolTipService.ToolTip>
    12. <StackPanel>
    13. <TextBlock Text="{Binding Path=Interpret, StringFormat='Interpret: \{0\}'}"/>
    14. <TextBlock Text="{Binding Path=Album, StringFormat='Album: \{0\}'}"/>
    15. </StackPanel>
    16. </ToolTipService.ToolTip>
    17. </TextBlock>
    18. <Border Name="brdAlbumZuPlaylistZufuegen" Height="{StaticResource listboxitemhoehe}" Grid.Column="0" Style="{DynamicResource Navigationsbuttons}" ToolTip="Füge alle Musiktitel dieses Albums der Playlist des gewählten Plattendecks zu..." HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
    19. <Border.InputBindings>
    20. <MouseBinding MouseAction="LeftClick" Command="{Binding DataContext.AlbumZuPlaylistZufuegen, ElementName=lstAlben}" CommandParameter="{Binding}"/>
    21. </Border.InputBindings>
    22. <Viewbox Stretch="Uniform">
    23. <Path Margin="4" Stretch="Uniform" Fill="{DynamicResource VordergrundfarbeBrush}" Data="xxx"/>
    24. </Viewbox>
    25. </Border>
    26. <Border Name="brdAlbumAbspielen" Height="{StaticResource listboxitemhoehe}" Grid.Column="1" Style="{DynamicResource Navigationsbuttons}" ToolTip="Spiele alle Musiktitel dieses Albums auf dem gewählten Plattendeck ab...">
    27. <Border.InputBindings>
    28. <MouseBinding MouseAction="LeftClick" Command="{Binding DataContext.AlbumAbspielen, ElementName=lstAlben}" CommandParameter="{Binding}"/>
    29. </Border.InputBindings>
    30. <Viewbox Stretch="Uniform">
    31. <Path Margin="4" Stretch="Uniform" Fill="{DynamicResource VordergrundfarbeBrush}" Data="yyy"/>
    32. </Viewbox>
    33. </Border>
    34. </Grid>
    35. </DataTemplate>
    36. </ListBox.ItemTemplate>
    37. </ListBox>


    Das zweite Problem ist, wenn ich nochmal auf die Schaltfläche klicke, wenn die Animation noch nicht abgeschlossen ist, wird die Farbe nicht wieder zurückgesetzt, sondern es wird eine zweite Animation gestartet, die als "Ausgangsfarbe" die aktuelle Farbe der ersten Animation nimmt. Kann man dieses Verhalten irgendwie blocken?

    Edit: OK, das mit der zweiten Animation kann ich wahrscheinlich mit dem Schlüsselwort From beheben, ich probier das mal...

    Freue mich auf Eure Antowrten :)

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

    Zur Fehlermeldung, müsste ich genauer schauen, hab dazu aber erst später Zeit.

    kafffee schrieb:

    wenn die Animation noch nicht abgeschlossen ist, wird die Farbe nicht wieder zurückgesetzt,


    Dann gib nicht nur "to" an, sondern auch "from". Dann sollte das schonmal funktionieren.
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D

    DTF schrieb:

    Zur Fehlermeldung, müsste ich genauer schauen, hab dazu aber erst später Zeit.


    Ah okay, bin für jede Hilfe dankbar

    DTF schrieb:

    Dann gib nicht nur "to" an, sondern auch "from". Dann sollte das schonmal funktionieren.


    Ja den Gedanke hatte ich auch schon, funktioniert aber nur mir "festen" Farben. Mit DynamicResource crasht das Programm und mit StaticResource passiert keine Animation....

    Edit: Ich befürchte fast, dasss das nur mir festen Farben funktioniert... Wäre nicht so schlimm, dann arbeite ich mit Opacity, das fuktioniert.... und zwar beide Probleme sind/wären damit gelöst...

    Jetzt bin ich aber auf ein weiteres Problem gestossen:

    Die Path-Elemente reagieren auf den Klick nur, wenn man quasi direkt auf das gezeichnete Objekt klickt. Wenn man auf den transparenten Bereich klickt, passiert gar nichts. Jetzt hab ich ja sowieso das Border immer drumrum. Gibt es eine Möglichkeit, per XAML auf das untergeordnete Element des Borders (bei mir also das Path) und dessen Fill-Eigenschaft zuzugreifen vom Storyboard aus? Ich hab da die Eigenschaft Storyboard.Target gefunden, kann man da vielleicht irgendwie mit x:Type Path oder etwas in der Art arbeiten? Denn IntelliSense zeigt mir da nicht wirklich was an... bei MS Docs bin ich da auch nicht fündig geworden, da gab es nur Storyboard.TargetName und Storyboard.TargetProperty. Ich will halt nicht jedes Path einzeln mit Name ansteuern, sondern das jeweils dem Border untergeordnete...

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

    kafffee schrieb:

    Mit DynamicResource crasht das Programm und mit StaticResource passiert keine Animation....


    Hast du einfach den Brush genommen oder dessen Color? Du musst schon zwischen Brush und Color unterscheiden, "From" oder "To" will eine Farbe keinen Brush.
    Mach einfach so, geht wunderbar:

    XML-Quellcode

    1. <Window x:Class="WpfApp1.MainWindow"
    2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    4. xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    5. xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    6. xmlns:local="clr-namespace:WpfApp1"
    7. mc:Ignorable="d"
    8. Title="MainWindow" Height="450" Width="800">
    9. <Window.Resources>
    10. <Color x:Key="ColorSmurfBlue" R="0" G="102" B="255" A="255"/>
    11. <SolidColorBrush x:Key="BrushSmurfBlue" Color="{StaticResource ColorSmurfBlue}"/>
    12. <Style TargetType="{x:Type Path}">
    13. <Style.Triggers>
    14. <EventTrigger RoutedEvent="MouseLeftButtonDown">
    15. <BeginStoryboard>
    16. <Storyboard>
    17. <ColorAnimation From="{StaticResource ColorSmurfBlue}" To="White" Duration="00:00:01" AutoReverse="True" Storyboard.TargetProperty="(Path.Fill).(SolidColorBrush.Color)"/>
    18. </Storyboard>
    19. </BeginStoryboard>
    20. </EventTrigger>
    21. </Style.Triggers>
    22. </Style>
    23. </Window.Resources>
    24. <Grid>
    25. <Border>
    26. <Canvas Width="100" Height="100" VerticalAlignment="Center" HorizontalAlignment="Center">
    27. <Path Fill="{StaticResource BrushSmurfBlue}" Data="M 0,0 L 100,50 L 0,100"/>
    28. </Canvas>
    29. </Border>
    30. </Grid>
    31. </Window>

    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D
    Ich habe eben den Post und Source genauer angeschaut, dabei bemerkt, das du auch das Problem hast mit dem klicken, so das nur wenn du im Path klickts der Path Animiert wird, liegt daran, das du im Style für die Path's den Trigger hast, so kann nur bei klick auf den Path reagiert werden. Ich muss gleich mal was nachlesen, dann mach ich da mal was.(Bin diese Woche auch nicht ganz taufrisch, hab einen Kingdom Come Marathon hinter mir, spiele das aktuell noch mal, diesmal in Schwierigkeitsgrad Hardcore, satte 100 Stunden in den letzten 9 Tagen)
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D
    Hab nun mal geschaut, ohne Tricks geht es nicht, evtl. mit einer AttachedProperty, würde evtl. auch mit einem RelayCommand gehen wo als Parameter die Canvas Instanz festgelegt wird(dann über die Childrens Property den Path holen), aber das finde ich zu viel UI im ViewModel. Da beim Mausklick aufs Canvas die Animation gestartet wird, kann man nur via ElementName das Target bekommen. So muss man dann aber bei jeden Canvas mit solch animierten Path-Fill-Color den Style reinbauen :( .

    XML-Quellcode

    1. <Canvas Width="100" Height="100" VerticalAlignment="Center" HorizontalAlignment="Center" Background="White">
    2. <Canvas.Triggers>
    3. <EventTrigger RoutedEvent="MouseLeftButtonDown">
    4. <EventTrigger.Actions>
    5. <BeginStoryboard>
    6. <Storyboard>
    7. <ColorAnimation From="{StaticResource ColorSmurfBlue}" To="White" Duration="00:00:01" AutoReverse="True" Storyboard.TargetName="thePath" Storyboard.TargetProperty="Fill.Color"/>
    8. </Storyboard>
    9. </BeginStoryboard>
    10. </EventTrigger.Actions>
    11. </EventTrigger>
    12. </Canvas.Triggers>
    13. <Path x:Name="thePath" Fill="{StaticResource BrushSmurfBlue}" Data="M 0,0 L 100,50 L 0,100"/>
    14. </Canvas>


    PS: @kafffee
    Mit einer AttachedProperty gehts wirklich und einfacher als wie bei jedem Canvas Style und Storyboard.... anzulegen.
    Das kannst du bei allen Canvas nutzen, vorraussetzung ist aber, das das erste Element des Canvas ein Shape ist, Also Rectangle, Ellispe, Path, wie alle was von Shape erbt.

    PPS:
    Hab den Code wieder gelöscht weil fehlte was, auch wenn die Animation funktionierte, schau einfach in die Projektmappe, hatte keine Lust das nochmal zu editieren.
    Dateien
    • WpfApp1.7z

      (2,99 kB, 119 mal heruntergeladen, zuletzt: )
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D

    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „DTF“ ()

    @DTF

    Okay AttachedProperties sind für mich noch Neuland, das muss ich mir mal noch in Ruhe anschauen.

    Hab grade zeitgleich beim Recherchieren eine noch einfachere Lösung gefunden: Man kann wohl noch ein zweites Path hernehmen, das das eigentliche Path mit dem Icon umhüllt und davon dann die Fill-Property auf Transparent setzen. Das klingt so als könnte es klappen, ich probier das mal aus und meld mich wieder...

    kafffee schrieb:

    Okay AttachedProperties sind für mich noch Neuland, das muss ich mir mal noch in Ruhe anschauen.


    Gabs schon mehrfach hier, auch bei der Titelleiste, erinnerst du dich nicht?
    Auch im Tutorial vom NoFear findest du solche. Sind sehr nützlich. Hatte das nochmal geupdated, lade die Mappe einfach noch mal runter.

    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „DTF“ ()

    Doch ich erinner mich dunkel. Habs damals einfach nicht gecheckt und hab das Fenster mit der Titelleiste dann im Code Behind mit der Methode DragMove verschoben. Das war eine von zwei oder drei Stellen im Code wo ich tatsächlich mal auf Code Behind zurückgegriffen hab...

    Ich hatte deine Mappe noch gar nicht runtergeladen (also wenn du die Mappe hier in diesem Thread meinst?). Würds dir was ausmachen das als Zip nochmal hochzuladen? Ansonsten ist auch egal du hast ja den Code gepostet das sollte langen ich geh jetzt mal von aus das der funktioniert...
    Funktionieren deine Slider nicht mit mausrad rauf/runter? Oder hast du das im Code Behind? Dann kannst du das auch mit AttachedProperties machen.

    Wenn du im XAML einer Property einen Wert zuweist, sollest du ja Wissen, woher die Stammen auch.
    beispiel:
    <SomeElement Property="Wert"/> , oder <Rectangle Fill=.../>
    Mit den AttachedProperties, zauberst du deine eigenen properties einfach so da rein. Auf deutsch: "Angehängte Eigenschaften", da ich ICommand für die Property nutze, kann man auch gleich im ViewModel bescheidsagen(Command.Execute). Du Kannst anstatt von ICommand auch eine Farbe nehmen und verwenden, oder sonst einen Typ.

    PS
    @kafffee
    Hier nochmal als zip:
    Dateien
    • WpfApp1.zip

      (6,2 kB, 1.148 mal heruntergeladen, zuletzt: )
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „DTF“ ()

    Meine Slider funktionieren derzeit mit MIDI-Befehlen von einem MIDI-kompatiblen Hardware-Mischpult ;)

    Aber hast recht so mit Mausrad das wär nice to have....

    Mal gucken vielleicht bekomm ich das mit Hilfe deines Beispiels hin...

    Edit: Hab mir grad nochmal das Kapitel von Nofear23m durchgelesen. Ich glaub ich habs verstanden diesmal, jetzt muss ichs nur noch in die Tat umsetzen...

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

    @DTF Bin gerade nochmal dabei das mit den Slidern zu lösen.

    Das Kapitel von Nofear23m hab ich verstanden denke ich. Unterschied ist ja, dass er da in seinem Beispiel mit einer Property arbeitet, die ja einen Wert hat. Bei dir in deinem Demo-Programm ändert sich ja nicht der Wert dieser Property, sondern du gehst mit einem Mausklick um... und genau da haperts bei mir noch, mir erschliesst sich nicht ganz, wie das funktioniert.

    Kannst du mir das mit ein paar Worten erklären? Das hab ich bis jetzt:

    VB.NET-Quellcode

    1. Public Class SliderMouseWheelControlAttachedProperty
    2. Inherits DependencyObject
    3. Public Shared ReadOnly MouseWheelDownCommandProperty As DependencyProperty = DependencyProperty.RegisterAttached("MouseWheelDownCommand", GetType(ICommand), GetType(SliderMouseWheelControlAttachedProperty), New PropertyMetadata(New PropertyChangedCallback(AddressOf MouseWheelDownCommandChanged)))
    4. Private Shared Sub MouseWheelDownCommandChanged(ByVal d As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
    5. Dim MeinSlider As Slider = CType(d, Slider)
    6. AddHandler MeinSlider.MouseWheel, AddressOf MouseWheel
    7. End Sub
    8. Private Shared Sub MouseWheel(ByVal sender As Object, ByVal e As MouseEventArgs)
    9. Dim MeinSlider As System.Windows.Controls.Slider = CType((CType(sender, Slider)), System.Windows.Controls.Slider)
    10. MeinSlider.Value += MeinSlider.Value
    11. End Sub
    12. Public Shared Sub SetMouseWheelDownCommand(ByVal slider As Slider, ByVal command As ICommand)
    13. slider.SetValue(MouseWheelDownCommandProperty, command)
    14. End Sub
    15. Public Shared Function GetMouseWheelDownCommand(ByVal slider As Slider) As ICommand
    16. Return TryCast(slider.GetValue(MouseWheelDownCommandProperty), ICommand)
    17. End Function
    18. End Class
    Hast du auch XAML dazu? Es reicht der Code vom Slider, wo du das mit dem MouseWheel nutzen willst. Ich habe ja Typ ICommand verwendet, im XAML nutze ich diese DependencyProperty, weise einen RelayCommand zu, das geht weil RelayCommand ja ICommand Implementiert, ich habe ICommand genommen, weil ich so auch im ViewModel informiert werde. Wenn du im Sample im ViewModel schaust, wird dort auch der Command ausgeführt. Ich mache dir dazu heute ein Sample, so das du keinen RelayCommand im ViewModel brauchst.

    Es geht bei dir aber schon in die richtige Richtung :thumbsup:

    Zeig aber noch den XAML Code vom Slider mit zuweisen eines Wert für die Property.
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D
    Naja, ob man nun ICommad oder sonst was nimmt, das läuft im Prinzip auf gleiche hinaus. Nur das man mit dem ICommand im ViewModel Informiert wird, beim MouseDown vom Canvas durch brauchbar, hätte Canvas auch Click, hätte ich den weitergeleitet. Beim Slider braucht man das ja nicht, da binden wir die Value vom Slider, die Property haben wir ja im ViewModel dann schon und können auf änderung reagieren.
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D
    So, geht gleich wieder mit kritik los, ;) . Du musst doch einiges nachholen. Auch in WinForms gibt es MouseEventArgs, z.B. für Clicks usw., aber auch MouseWheelEventArgs, das sollte dir eigendlich geläufig sein. Das Mausrad kann man rauf und runter drehen, MouseEventArgs hat keinerlei Informationen darüber. MouseWheelEventArgs hat das Feld Delta, mit dem können wir feststellen, ob nun rauf oder runter gedreht wurde.

    Warum das doppelte CType?
    Dim MeinSlider As System.Windows.Controls.Slider = CType((CType(sender, Slider)), System.Windows.Controls.Slider)

    So genug mit der Kritik :P ;) . Nun zum wesentlichen, anstatt ICommand habe ich nun Double als Typ für die DependencyProperty genommen. Damit legen wir dann fest um wie viel der Wert geändert werden soll.
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class SliderMouseWheel
    2. Inherits DependencyObject
    3. Public Shared ReadOnly MouseWheelChange As DependencyProperty = DependencyProperty.RegisterAttached("MouseWheelChangeProperty", GetType(Double), GetType(SliderMouseWheel), New PropertyMetadata(New PropertyChangedCallback(AddressOf MouseWheelChangeChanged)))
    4. Private Shared Sub MouseWheelChangeChanged(ByVal d As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
    5. Dim slider As Slider = DirectCast(d, Slider)
    6. AddHandler slider.MouseWheel, AddressOf OnMouseWheel
    7. End Sub
    8. Private Shared Sub OnMouseWheel(sender As Object, e As MouseWheelEventArgs)
    9. Dim slider As Slider = DirectCast(sender, Slider)
    10. Dim sliderValue = slider.Value
    11. Dim change As Double = DirectCast(slider.GetValue(MouseWheelChange), Double)
    12. If e.Delta > 0 Then
    13. sliderValue += change
    14. ElseIf e.Delta < 0 Then
    15. sliderValue -= change
    16. End If
    17. slider.Value = Clamp(sliderValue, slider.Minimum, slider.Maximum)
    18. End Sub
    19. Private Shared Function Clamp(value As Double, min As Double, max As Double) As Double
    20. If value < min Then value = min
    21. If value > max Then value = max
    22. Return value
    23. End Function
    24. Public Shared Sub SetMouseWheelChangeProperty(uiElement As UIElement, value As Double)
    25. uiElement.SetValue(MouseWheelChange, value)
    26. End Sub
    27. Public Shared Function GetMouseWheelChangeProperty(uiElement As UIElement) As Double
    28. Return DirectCast(uiElement.GetValue(MouseWheelChange), Double)
    29. End Function
    30. End Class


    XML-Quellcode

    1. <Slider Minimum="0" Maximum="100" local:SliderMouseWheel.MouseWheelChangeProperty="0.25" />


    Und schon haben wir solch eine Funktionalität als AttachedProperty hineingezaubert,. Aber mach demnächst doch besser einen neuen Thread auf, das hat ja nichts mehr mit dem ursprünglichen Thema zu tun.

    PS. @kafffee
    Kleine änderung, besser das Event wieder entfernen, sollte der Wert geändert werden, würde sonst mehrfach das Event gefeuert, es könnte ja bereits für dieses Element abonniert sein.

    VB.NET-Quellcode

    1. Private Shared Sub MouseWheelChangeChanged(ByVal d As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
    2. Dim slider As Slider = DirectCast(d, Slider)
    3. RemoveHandler slider.MouseWheel, AddressOf OnMouseWheel
    4. AddHandler slider.MouseWheel, AddressOf OnMouseWheel
    5. End Sub

    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D

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

    Jou das versteh ich schon besser. Noch eine Rückfrage:

    VB.NET-Quellcode

    1. Public Shared ReadOnly MouseWheelChange As DependencyProperty = DependencyProperty.RegisterAttached("MouseWheelChangeProperty", GetType(Double), GetType(SliderMouseWheel), New PropertyMetadata(New PropertyChangedCallback(AddressOf MouseWheelChangeChanged)))


    Seh ich das richtig, dass hier...:

    New PropertyMetadata(New PropertyChangedCallback(AddressOf MouseWheelChangeChanged))

    ... ja beim Initialisieren MouseWheelChangeChanged aufgerufen wird und dort dann quasi das MouseWheel-Event abonnniert wird? Weil dann hab ichs glaube ich verstanden...

    PS: Hab dann auch noch eine Kleinigkeit eingebaut, dass egal was für Min-/Maximum der Slider hat, der Value des Sliders immer nach 10 Schritten ganz oben/unten ist:

    VB.NET-Quellcode

    1. Dim change As Double = (slider.Maximum - slider.Minimum) / 10


    Edit:
    es könnte ja bereits für dieses Element abonniert sein.

    Du meinst das Event könnte schon an irgend einer anderen Stelle im Projekt abonniert sein? Also jetzt nicht in dem Code hier?