views:

531

answers:

3

Hi I am right now in an project using VB.NET and needs to translate this C# code into VB.NET

oldCommand.CanExecuteChanged -= commandReference.CanExecuteChanged;

newCommand.CanExecuteChanged += commandReference.CanExecuteChanged;

For me it seems like the an event hooking up on an another event? But I have tried everything to translate this into VB.NET code? I have found out that EventHandler management in VB.NET is far from as good it is in C# as many other things.

So how can I do this in VB.NET?

Edit: here is the code I want to transalate all code is easy to translate but the code in the method OnCommandChanged.

public class CommandReference : Freezable, ICommand
{
    public static readonly DependencyProperty CommandProperty = DependencyProperty.Register("Command",
        typeof(ICommand),
        typeof(CommandReference),
        new PropertyMetadata(new PropertyChangedCallback(OnCommandChanged)));

    public ICommand Command
    {
        get { return (ICommand)GetValue(CommandProperty); }
        set { SetValue(CommandProperty, value); }
    }

    #region ICommand Members

    public bool CanExecute(object parameter)
    {
        if (Command != null)
            return Command.CanExecute(parameter);
        return false;
    }

    public void Execute(object parameter)
    {
        Command.Execute(parameter);
    }

    public event EventHandler CanExecuteChanged;

    private static void OnCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        CommandReference commandReference = d as CommandReference;
        ICommand oldCommand = e.OldValue as ICommand;
        ICommand newCommand = e.NewValue as ICommand;

        if (oldCommand != null)
        {
            oldCommand.CanExecuteChanged -= commandReference.CanExecuteChanged;
        }
        if (newCommand != null)
        {
            newCommand.CanExecuteChanged += commandReference.CanExecuteChanged;
        }
    }

    #endregion

    #region Freezable

    protected override Freezable CreateInstanceCore()
    {
        throw new NotImplementedException();
    }

    #endregion
}
+2  A: 

"as far from as good"? It's just as good, the semantics are just different :)

Try

RemoveHandler okButton.Click, addressof OkButton_ClickHandler

AddHandler okButton.Click, addressof OkButton_ClickHandler

Update

Hi, I missed the intent of your question, apologies.

I'm puzzled by your approach, when you put += and -= between the two event, you're not hooking and unhooking the events, you're only adding and removing the the handlers that exist at that moment. i.e. you're not hooking event a to event b, you're hooking the handlers that b currently has assigned to a. So if (for example) after the assignment all the handlers are removed from b they will still be assigned to a.

I'm probably missing something obvious sorry, also I don't have time right now to dig into how Dependency properties are implemented in WPF, which is where I'd look next.

Sorry I can't be of more help.

Binary Worrier
Have you tested that code and compiled it? I have tested just that and got the following compiler error:Error 1 'AddressOf' operand must be the name of a method (without parentheses)It seems like it wont allow me to use addressof on an event.
It wasn't obvious what you're arguements were, so I updated the answer to make it clearer. The first argurment is the event, the second is the address of the method to be called in response to the event.
Binary Worrier
ok, but as you see that solution wont solve my problem, my scenario is that I have two objects in matter of fact I have two instances of ICommand which both has an CanExecuteChanged event on them, this method will link the two events together. So I can't solve it as you presented it now :(. Is this an limitation in Vb.Net event handling?
No more clue?? :|
A: 

I think you're looking for AddHandler and RemoveHandler, which are built-in functions. Not as clear-cut as C#, but useful.

Also covered in the VB Programming Guide.

Jeff Wilcox
They don't help me :(
A: 

I run into a similar problem when I was implementing an special INotifyCollectionChanged when I needed to know if the instance had event handlers attached.

After a little bit of searching, I took a page out of the ObservableCollecion(Of T) in order to do it.

The code you're trying to convert to VB is:

public event EventHandler CanExecuteChanged; 

private static void OnCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
{ 
    CommandReference commandReference = d as CommandReference; 
    ICommand oldCommand = e.OldValue as ICommand; 
    ICommand newCommand = e.NewValue as ICommand; 

    if (oldCommand != null) 
    { 
        oldCommand.CanExecuteChanged -= commandReference.CanExecuteChanged; 
    } 
    if (newCommand != null) 
    { 
        newCommand.CanExecuteChanged += commandReference.CanExecuteChanged; 
    } 
} 

you need a little bit more code, but it's something like this:

Private __CanExecuteCommand as EventHandler

Public Custom Event CanExecuteChanged As EventHandler 
    AddHandler(ByVal value As EventHandler)
        Dim handler2 As EventHandler
        Dim canExecuteCommand = __CanExecuteCommand
        Do
            handler2 = canExecuteCommand
            Dim handler3 = DirectCast(System.Delegate.Combine(handler2, value), EventHandler)
            canExecuteCommand = Interlocked.CompareExchange((__CanExecuteCommand), handler3, handler2)
        Loop While (Not canExecuteCommand Is handler2)
        __CanExecuteCommand = canExecuteCommand
    End AddHandler
    RemoveHandler(ByVal value As EventHandler)
        Dim handler2 As EventHandler
        Dim canExecuteCommand = __CanExecuteCommand
        Do
            handler2 = canExecuteCommand
            Dim handler3 = DirectCast(System.Delegate.Remove(handler2, value), EventHandler)
            canExecuteCommand = Interlocked.CompareExchange((__CanExecuteCommand), handler3, handler2)
        Loop While (Not canExecuteCommand Is handler2)
        __CanExecuteCommand = CanExecuteCommand
    End RemoveHandler
    RaiseEvent(ByVal sender As Object, ByVal e As EventArgs)
        If (__CanExecuteCommand IsNot Nothing) Then
            __CanExecuteCommand.Invoke(sender, e)
        End If
    End RaiseEvent
End Event

Private Shared Sub OnCommandChanged(d as DependencyObject, e as DependencyPropertyChangedEventArgs) 

    Dim commandReference = CType(d, CommandReference) 
    Dim oldCommand = CType(e.OldValue, ICommand) 
    Dim newCommand = CType(e.NewValue, ICommand)

    If (oldCommand IsNot Nothing) Then
        RemoveHandler oldCommand.CanExecuteChanged, commandReference.__CanExecuteChanged; 
    End If
    If (newCommand IsNot Nothing)  Then
        AddHandler newCommand.CanExecuteChanged, commandReference.__CanExecuteChanged; 
    End If

End Sub 

So now you can not only check if the event has handlers as also move them around.

Paulo Santos