views:

283

answers:

1

I have a "partial" class in VB.NET. Half of it is auto generated by a code generation tool. That half implements INotifyPropertyChanged, so any properties in that part of the partial class raise the PropertyChanged event.

In my "custom" part of the class, I declare another property that depends on one of the properties in the auto-generated side. Therefore, when that auto-generated property changes, I also want to raise a PropertyChanged event on my custom property that depends on it.

If I go into the generated part of the class and raise the event there, that will get overwritten if I ever re-generate that part, so I don't want to do that. I would rather add an event handler in my side of the partial class that checks if the generated property changed, and if so, raise another event for my custom property.

I'm trying to write this to hook my own event, but it's not working:

Private Sub MyProperty_PropertyChangedHandler( _
        ByVal sender As Object, ByVal e As PropertyChangedEventArgs _
        ) Handles Me.PropertyChanged
    Select Case e.PropertyName
        Case "AutoGenProperty"
            RaiseEvent PropertyChanged(Me, _
                New PropertyChangedEventArgs("MyProperty"))
    End Select
End Sub

I'm assuming it's because normally you'd use the WithEvents keyword to tell the compiler that you're subscribing to events from that object. I don't have a clue how to do this inside of the class that's actually raising the event, or if that's even possible.

+1  A: 

In your constructor, you need something on the lines of

AddHandler PropertyChanged, addressof MyProperty_PropertyChangedHandler

and remove the "Handles Me.PropertyChanged" from your event handler, basically your adding the event handler manually

where "PropertyChanged" is the name of the event you want to catch.

UPDATE

You can't do that because the the ctor is in the auto generated portion of the class. So you can use the following idiom to add the handler for you. You're going to specify a private class inside your class, and puit on as a private member on your new class, when the private member is constructed you add the handler for the event.

Public Partial MyClass
    private class MyInitialiser
       public sub new(byval myParent as MyClass)
          Addhandler myParent.PropertyChanged, addressof myParent.MyProperty_PropertyChangedHandler
       end sub
    end class
    private _myInitialiser as new MyInitialiser(me)
. . .
End Class

The above is untested, but I've done this lots of times before.

Hope it helps :)

Binary Worrier
The constructor is in the generated part of the class...
Scott Whitlock
I like the update... looks like genius - I'll give it a try.
Scott Whitlock
It still doesn't work. A breakpoint on the first line of the event handler isn't being hit.
Scott Whitlock
Sorry dude :( Does the addhandler in the initialisers constructor run? If that's not the problem I'm afraid I'm out of ideas. Unmark this as the correct answer, you'll be more likely to get more responses without a selected answer.
Binary Worrier
It is the correct answer in the normal case. My class is being de-serialized after travelling over the wire, and the nested class instance isn't being instantiated when the object is de-serialized. It does work when I instantiate my object normally. The de-serialization issue is another question.
Scott Whitlock
I see, it may be time to ask another question. Sorry I couldn't be of more help.
Binary Worrier
Np. Actually to solve the problem with de-serialization, I just need to add a method with the attribute <OnSerializing()> that sets _myInitlializer to new MyInitializer(Me). Unfortunately, I'm using Silverlight and that attribute (and interface) isn't implemented in Silverlight! ahhhh! (Thanks!)
Scott Whitlock