For a project I have to use VB.NET. I am going to use MVVM, so I have to implement a RelayCommand
class.
In C#, the class looks like this:
class ActionCommand : ICommand
{
private Action<object> execute;
private Predicate<object> canExecute;
private event EventHandler CanExecuteChangedInternal;
public ActionCommand(Action<object> execute) : this(execute, DefaultCanExecute) { }
public ActionCommand(Action<object> exec, Predicate<object> canExec)
{
if (exec == null)
throw new ArgumentNullException("execute");
if (canExec == null)
throw new ArgumentNullException("canExecute");
execute = exec;
canExecute = canExec;
}
public event EventHandler CanExecuteChanged
{
add { CanExecuteChangedInternal += value; }
remove { CanExecuteChangedInternal -= value; }
}
public bool CanExecute(object param)
{
return canExecute != null && canExecute(param);
}
public void Execute(object param)
{
execute(param);
}
public void OnCanExecuteChanged()
{
EventHandler handler = CanExecuteChangedInternal;
if (handler != null)
handler.Invoke(this, EventArgs.Empty);
}
public void Destroy()
{
canExecute = _ => false;
this.execute = _ => { return; };
}
private static bool DefaultCanExecute(object param)
{
return true;
}
}
My version in VB.NET looks like this:
Public Class RelayCommand : Implements ICommand
Dim _execute As Action(Of Object)
Dim _canExecute As Predicate(Of Object)
Dim canExecuteChangedInternal As EventHandler
Sub New(ByVal execute)
Me.New(execute, DefaultCanExecute)
End Sub
Sub New(ByVal execute As Action(Of Object), ByVal canExec As Predicate(Of Object))
If execute = Nothing Then
Throw New ArgumentException("execute")
End If
If canExec = Nothing Then
Throw New ArgumentException("canExec")
End If
_execute = execute
_canExecute = canExec
End Sub
Public Function CanExecute(ByRef param As Object) As Boolean
Return _canExecute <> Nothing And _canExecute(param)
End Function
Public Sub Execute(ByVal obj As Object)
_execute(obj)
End Sub
Public Custom Event CanExecuteChanged As EventHandler
AddHandler(ByVal value As EventHandler)
AddHandler canExecuteChangedInternal, AddressOf value
End AddHandler
RemoveHandler(value As EventHandler)
RemoveHandler canExecuteChangedInternal, AddressOf value
End RemoveHandler
RaiseEvent(sender As Object, e As EventArgs)
End RaiseEvent
End Event
Public Sub OnCanExecuteChanged(ByVal param As Object)
Dim handler As EventHandler = canExecuteChangedInternal
If handler <> Nothing Then
handler.Invoke(Me, EventArgs.Empty)
End If
End Sub
Public Sub Destroy()
_canExecute = Function(param As Object)
Return False
End Function
Me._execute = Sub()
Return
End Sub
End Sub
Private Shared Function DefaultCanExecute(ByVal param As Object) As Boolean
Return True
End Function
End Class
Now I have the following problems in VB:
- In my constructor
DefaultCanExecute
is not accepted as a parameter for the other constructor, but in C# it works fine. - Adding and removing the
EventHandlers
does not work. The error message is: "value is not a name of a method". But it's an event handler, isn't it? The C# version works here, too.
There are a number of things that are odd about your conversion: 1. You need to use 'Is' and 'IsNot' for reference types. 2. You omitted the type for your first constructor. 3. You omitted a parameter for the second lambda in the 'Destroy' method.
Try the following:
Thanks to Dave, I was able to get everything sorted out. If anyone is interested in the final version of the class, here it is: