0
votes

So for the last day or two I've been studying this article in order to get some exposure to dependency properties and routed commands, and hopefully leverage some of the sample code to solve a content scaling problem in another project. That project happens to be written in vb.net, and this sample code is in C#.

Okay, no problem. Most of the tutorials and demo projects that I have seen use C#, and I have found that reading the code and writing its equivalent in vb.net is a really good way to understand what's actually happening and to get more comfortable using either. It's time consuming, but worthwhile at my experience level (#00FF00)

It wasn't long before I encountered problems with events with callback methods. Consider this method:

public static class AnimationHelper
{

...

public static void StartAnimation(UIElement animatableElement,
                                  DependencyProperty dependencyProperty,
                                  double toValue,
                                  double animationDurationSeconds,
                                  EventHandler completedEvent)
{
    double fromValue = (double)animatableElement.GetValue(dependencyProperty);

    DoubleAnimation animation = new DoubleAnimation();
    animation.From = fromValue;
    animation.To = toValue;
    animation.Duration = TimeSpan.FromSeconds(animationDurationSeconds);

    animation.Completed += delegate(object sender, EventArgs e)
    {
        //
        // When the animation has completed bake final value of the animation
        // into the property.
        //
        animatableElement.SetValue(dependencyProperty, animatableElement.GetValue(dependencyProperty));
        CancelAnimation(animatableElement, dependencyProperty);

        if (completedEvent != null)
        {
            completedEvent(sender, e);
        }
    };

    animation.Freeze();

    animatableElement.BeginAnimation(dependencyProperty, animation);
}

Transcribing this method to vb.net is straightforward except for the way to properly handle DoubleAnimation's Completed event and the callback method. My best attempt looks like:

Public NotInheritable Class AnimationHelper

...

Public Shared Sub StartAnimation(...)

...

animation.Completed += Function(sender As Object, e As EventArgs)

            animatableElement.SetValue(dependencyProperty, animatableElement.GetValue(dependencyProperty))
            CancelAnimation(animatableElement, dependencyProperty)
            RaiseEvent completedEvent(sender, e)
        End Function
...

End Sub

This results in two complaints:

  1. 'completedEvent' is not an event of [namespace].AnimationHelper

  2. 'Public Event Completed(...)' is an event and cannot be called directly. Use RaiseEvent...

(1) is a bit of a mystery to me because completedEvent (As EventHandler) is one of the parameters in the method declaration. Removing RaiseEvent from the head of the line and calling it like an ordinary method appears to satisfy visual studio, but I don't whether that will work at runtime or if it's valid to do so at all. In (2) the syntax looks dubious to me, adding RaiseEvent to the head of the line causes similar complaints similar to (1).

I'm going to continue scouring stack and the greater internet for good primers on delegates and events in vb.net since it's obviously time I stopped avoiding learning how they work. In the meantime, advice/suggestions are most welcome.

2

2 Answers

0
votes
  1. Why do you try raising that event handler? An EventHandler is just a delegate. Simply execute it as in C#:

    if completedEvent IsNot Nothing then
        completedEvent(sender, e)
    end if
    
0
votes

I believe the main problem here is that you're not adding the handler in the VB way with AddHandler. If you rewrite the code as:

Dim handler As EventHandler = Sub(sender, e)
    x.SetValue(dependencyProperty, x.GetValue(dependencyProperty))
    CancelAnimation(x, dependencyProperty)
    ' See note below...
    RaiseEvent completedEvent(sender, e)
End Sub

AddHandler animation.Completed, handler

... I believe it will work. It's not clear whether the RaiseEvent part will still cause problems, but at least subscribing to animation.Completed should be okay. If the RaiseEvent part causes problems, invoke the delegate directly as per Daniel's answer.

Note the use of Sub here rather than Function, as the delegate doesn't return anything.