Property access must assign to the property or use its value Action of T delegate

ola

Member
Joined
Sep 20, 2010
Messages
7
Programming Experience
5-10
Hi This code snippet was converted from the c# snippet on this link :

A ChildWindow management service for MVVM applications


There are two classes in this snippet first is my confirmessage class

Public Class ConfirmMessage
''' <summary>

''' Initializes a new instance of the <see cref="ConfirmMessage"/> class.
''' </summary>
''' <param name="message">The message.</param>
''' <param name="callback">The callback.</param>
Public Sub New(ByVal message As String, ByVal callback As Action(Of Boolean?))
Me.Message = message
Me.Callback = callback
End Sub



Public Property Callback() As Action(Of Boolean?)
Get
Return m_CallBack
End Get
Set(ByVal value As Action(Of Boolean?))
m_CallBack = value
End Set
End Property
Private m_CallBack As Action(Of Boolean?)



''' <summary>
''' Gets or sets the message.
''' </summary>
''' <value>The message.</value>
Public Property Message() As String
Get
Return m_Message
End Get
Set(ByVal value As String)
m_Message = value
End Set
End Property
Private m_Message As String

End Class


then In my Service I am doing this

'ConfirmDialog is a Childwindow
Public Sub ShowConfirmDialog(ByVal message As ConfirmMessage)

Dim dialog As New ConfirmDialog() 'reference to the childwindow we want to display

dialog.Message = message.Message

AddHandler dialog.Closed, Sub(s, e) message.Callback(dialog.DialogResult)

dialog.Show()

End Sub



Now this works fine in C# , however in vb,net the line where I add the event handler generates the following error on the message.callback property : Property access must assign to the property or use its value

I am tearing out my hair on this I have never used the Action of T delegate before so could i be missing something simeple ? I can provide the c# code as well.

thanks in advance.
 
Action(Of T) is a delegate, which you can Invoke (ie call the method it points to):
VB.NET:
.Callback.Invoke(dialog.DialogResult)

'here the value of .Callback property is retrieved (getter), then the delegate instance is used to call the .Invoke member
Boolean? is type Nullable(Of Boolean) and this does not correspond to the DialogResult type you're passing in. Change the type to Action(Of DialogResult) and all goes well. Or if Boolean? is correct pass in either a Boolean value or Nothing :)
 
You could do it like this:

VB.NET:
AddHandler dialog.Closed, AddressOf dialog_Closed

VB.NET:
        Sub dialog_Closed(ByVal sender As Object, ByVal e As EventArgs)
            message.Callback(dialog.DialogResult)
        End Sub

Or since you're using .NET 4.0 you can create a sub inline to handle it:

VB.NET:
            AddHandler dialog.Closed,
                (Sub(s As Object, e As EventArgs)
                     message.Callback(dialog.DialogResult)
                 End Sub)
 
VB.NET:
message.Callback(dialog.DialogResult)
For some reason, in this case this is not valid in VB.Net, probably this is the compiler getting confused. Now if you change it to this it works without explicitly calling the Invoke member:
VB.NET:
Dim cb = message.Callback 'type inferred
AddHandler dialog.Closed, Sub(s, e) cb(True)

Or since you're using .NET 4.0 you can create a sub inline to handle it:
That part in OP is equivalent and valid.
 
That's odd. I'm positive I used something exactly like that in the last project I was on without having to explicitly call Invoke. I'll dig around for the code when I've got some downtime.
 
As you see in my last example it is calling Invoke implicitly, only not directly from that property. (it is not related to the Nullable, by the way)
 
For some reason, in this case this is not valid in VB.Net, probably this is the compiler getting confused. Now if you change it to this it works without explicitly calling the Invoke member:
VB.NET:
Dim cb = message.Callback 'type inferred
AddHandler dialog.Closed, Sub(s, e) cb(True)


That part in OP is equivalent and valid.

Wow Infering they type worked , very strange, I had already tried using and Inline sub to add the handler with no luck, i will proceed with further testing. From what I hear inline subs can cause memory leaks since you have no way to remove the handler when you are done though.
at least it got me around that anoying error. I will keep you guys posted and thanks alot
 
You were right right JohnH i totally forgot that the Action(of T) type was an invokable delegate, it seems in C# that is infered automatically ? and in vb.net we have to explicitly invoke the delegate even when added as a handler. This code worked :

Public Sub ShowConfirmDialog(ByVal message As ConfirmMessage)
Dim dialog As New ConfirmDialog()
'Dim vm As New ConfirmMessageViewModel
dialog.Message = message.Message
AddHandler dialog.Closed, Sub(s, e) message.Callback.Invoke(dialog.DialogResult)

' Dim cb = message.Callback 'type inferred
' AddHandler dialog.Closed, Sub(s, e) cb(True)

dialog.Show()
End Sub

the commented out code where you infered the type of the the delegate function works as well

thanks ! I knew it was something simple
 
From what I hear inline subs can cause memory leaks since you have no way to remove the handler when you are done though.
In this case the type instance it is attached to is disposed after callback, so the memory is released and should be reclaimed next collection along with the dialog.

If it were not, if would be possible to hold a reference to the anonymous sub and use that reference with RemoveHandler. Since also the dialog instance is required in same call you could keep it with the dialog itself (.AnonSub As EventHandler) and release it after event was called (OnClosed, final call: RemoveHandler Me.Closed, AnonSub).

One more thing, Form.Closed event was obsolete after .Net 1.1, use FormClosed event instead.

And another, relaxed delegates allow you to leave out the method parameters when they are not used: Sub() message.Callback...
 
Back
Top