0

I have found some really interesting code for wiring up IPropertyChanged, To see the article click here.

My problem is after I have converted it to VB.Net I am receiving a compiler error in OnPropertyChanged method on the last line - OnPropertyChanged(body.Member.Name)

Data type(s) of the type parameter(s) in method 'Protected Overridable Sub OnPropertyChanged(Of T)(selectorExpression As System.Linq.Expressions.Expression(Of System.Func(Of T)))' cannot be inferred from these arguments. Specifying the data type(s) explicitly might correct this error.

Can someone help me correct the code to remove the error please?

Original C# Version:

protected virtual void OnPropertyChanged<T>(Expression<Func<T>> selectorExpression)
{
    if (selectorExpression == null)
        throw new ArgumentNullException("selectorExpression");
    MemberExpression body = selectorExpression.Body as MemberExpression;
    if (body == null)
        throw new ArgumentException("The body must be a member expression");
    OnPropertyChanged(body.Member.Name);
}

protected bool SetField<T>(ref T field, T value, Expression<Func<T>> selectorExpression)
{
    if (EqualityComparer<T>.Default.Equals(field, value)) return false;
    field = value;
    OnPropertyChanged(selectorExpression);
    return true;
}

After it has been converted to VB.Net

Protected Overridable Sub OnPropertyChanged(Of T)(selectorExpression As Expression(Of Func(Of T)))
    If selectorExpression Is Nothing Then
        Throw New ArgumentNullException("selectorExpression")
    End If
    Dim body As MemberExpression = TryCast(selectorExpression.Body, MemberExpression)
    If body Is Nothing Then
        Throw New ArgumentException("The body must be a member expression")
    End If
    OnPropertyChanged(body.Member.Name)//====this is the line with the compiler error======
End Sub

Protected Function SetField(Of T)(ByRef field As T, value As T, selectorExpression As     Expression(Of Func(Of T))) As Boolean
    If EqualityComparer(Of T).[Default].Equals(field, value) Then
        Return False
    End If
    field = value
    OnPropertyChanged(selectorExpression) 
    Return True
End Function
Community
  • 1
  • 1
scott_f
  • 838
  • 8
  • 17
  • What could be wrong with the question? Why the down vote? You shouldn't down vote because I answered it myself... – scott_f Jan 03 '15 at 07:00

2 Answers2

4

In VB it's much simpler than that... Just stick an Implements INotifyPropertyChanged at the top of your class.

The OnPropertyChanged sub is just a shortcut to raising the event.

Imports System.ComponentModel

Public Class SomeClass
    Implements INotifyPropertyChanged

    Public Event PropertyChanged(sender As Object, e As PropertyChangedEventArgs) _
        Implements INotifyPropertyChanged.PropertyChanged

    Protected Sub OnPropertyChanged(ByVal propName As String)
        RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propName))
    End Sub

    Private _someProperty As String = ""
    Public Property SomeProperty As String
        Get
            Return _someProperty
        End Get
        Set(value As String)
            _someProperty = value
            OnPropertyChanged("SomeProperty")
        End Set
    End Property
End Class

Or if you want something without magic string that you can copy and paste everywhere, so long as you don't mind using reflection:

OnPropertyChanged(System.Reflection.MethodInfo.GetCurrentMethod.Name.Replace("set_", ""))

Or, if you are using .NET 4.5+, change your OnPropertyChanged declaration to:

Private Sub OnPropertyChanged(<CallerMemberName> Optional ByVal propName As String = Nothing)

And call it without arguments.

Drunken Code Monkey
  • 1,796
  • 1
  • 14
  • 18
  • *Or if you want something without magic string that you can copy and paste everywhere, so long as you don't mind using reflection:* Does `CallerMemberNameAttribute ` not work for VB.NET? – ta.speot.is Jan 03 '15 at 04:21
  • Only in .NET 4.5... Unfortunate that it took this long to make it in... – Drunken Code Monkey Jan 03 '15 at 04:22
  • 3
    @DrunkenCodeMonkey: The attribute itself can work in .NET 2.0 too if you copy/paste it: http://www.thomaslevesque.com/2012/06/13/using-c-5-caller-info-attributes-when-targeting-earlier-versions-of-the-net-framework/ The important thing is though you need C#5 compiler, which comes from VS2012. Useful if you work with 2013, but target older projects ;) – Erti-Chris Eelmaa Jan 03 '15 at 09:18
  • @Chris Eelmaa very useful. I was going to ignore the attribute as I have to target older frameworks, so good to know! – scott_f Jan 04 '15 at 21:55
0

I worked out that I needed to add this code from the article:

Public Event PropertyChangedHandler As PropertyChangedEventHandler 

Protected Sub OnPropertyChanged(propertyName As String)
    RaiseEvent PropertyChangedHandler(Me, New PropertyChangedEventArgs(propertyName))
End Sub
scott_f
  • 838
  • 8
  • 17
  • 1
    Actually this is the answer that would have solved my question had somebody else posted it first and is why I included as an answer as I am answering my own question. – scott_f Jan 03 '15 at 05:38
  • 2
    @scott_f: please ignore them, if you solved your own question it is acceptable to post it as an answer: http://stackoverflow.com/help/self-answer – Qantas 94 Heavy Jan 03 '15 at 06:09