none
Type 'System.ComponentModel.PropertyChangedEventHandler' cannot be serialized. ?

    Question

  • I am in jepardy of losing the fight to move from winforms to silverlight because I can't get our class library to work with WCF.  I am trying to use a class library that implements INotifyDataChanged to bubble changes up through nested objects. Nothing special, lower objects use the PropertyChanged event to set a dirty flag and then bubble that change up to higher level classes. Works dandy in winforms but now that we are trying to use WCF and Silverlight the whole thing is blowing up in my face. 

     First, I fought through an obscure error that had to do with implicit members declared by VB.net. My event in the base class was called PropertyChanged and unbeknownst to me, there is an implicit member created by VB called <eventname>Event - in this case, PropertyChangedEvent. So, when the AddService tool tried to add a property to the proxy class called propertychangedevent, I got a compiler error. (ugh!) Anyway, got that one solved (http://msdn.microsoft.com/en-us/library/ms184639.aspx) but I am now getting a 404 service returned an unexpected response error. No, there is no domain crossing going on, it's all on localhost and still happens even if I use the computer name instead of localhost. 

     So, in a desparate attempt to avoid my boss from shutting this whole experiment down, I created a simple class with three properties and used that in my service and everything works just fine. For the next step, I added the INotifyPropertyChanged interface to the simple class and now I get the following error:

    There was an error while trying to deserialize parameter http://tempuri.org/:GetSimpleClassResult.  Please see InnerException for more details.

    Inner Exception: Type 'System.ComponentModel.PropertyChangedEventHandler' cannot be serialized. Consider marking it with the DataContractAttribute attribute, and marking all of its members you want serialized with the DataMemberAttribute attribute.

    This is messed up. I am looking at the example in the silverlight tutorials that implements INotifyPropertyChanged!!!! (http://silverlight.net/learn/tutorials/databinding.aspx) I have tried adding the DataMember attribute but the compiler complains that it is not valid on this declaration type.

    Any help would be fantastic. I don't understand what is going wrong and these seem to be very simple things that I am trying to do. Let me know if you need any code. I'll post my whole SVN reposity if it will help (just kidding!).

     Cheers,

    D

     

    Thursday, October 02, 2008 6:03 PM

Answers

  • Hello, are you trying to implement INotifyPropertyChanged on the server side? This will not work. INotifyPropertyChanged should be used on the client side only. It's used purely for client side data binding. WCF knows nothing about your client application's data binding. After all why it cares? If a property is changed on the client, when you call a web service, you passing the updated object as a parameter, and the service will automatically get the updated object. You implement INotifyPropertyChanged when, say, you have a ListBoxItem and a ContentControl bound to the same item. You modify a property in the source item with a TextBox in the ContentControl, and you want the ListBoxItem to update automatically. Other than such scenarios, you don't need this interface.

    I wonder if you want the object on the server side to be updated automatically together with the client object. If so, I think you have some misunderstanding with web services. In a web service's data contract, you have to keep your object model as simple as possible. Web service is very different from traditional technologies. Server and client communicates in the xml format. So everything must be able to be serialized by xml. Also web services work in a stateless model. Modifying an object on the client will not affect the server at all, no matter what interface you implement. Actually the instance of object on the client is completely different from the instance on the server. The client object may be a .NET object, while the server one may be a Java object. To get the updated object to the server, you have to call a service method. Under the hook, the client object will be serialized to an xml file, sent to the server, and then deserialized to a server object.

    This model have a lot of benefits. Most of all, now client and server are loosely coupled. If you're not accustomed to this model, then please don't use SOA. Silverlight works best with the service oriented architecture. So that means Silverlight is not the proper technology for you... But why not continue using Windows Forms while it serves you well? Unless you want your application to run cross platform, and requires extremely rich content, I don't see much benefits in Silverlight. Windows Forms serves very well for most business applications where you simply need to display data in a DataGrid, and update data in database.

    Anyway, if your company decides to adopt SOA (which is a world trend), sooner or later you'll have to be accustomed with the web service model, no matter whether you want to use Silverlight or not...

    Finally, if you create a normal DataContract in a WCF service, and add a service reference in your Silverlight application, you'll notice the generated classes all implement INotifyPropertyChanged automatically. We know this interface is very important in data binding, so the service reference tool generate it automatically. But once again, please understand this has nothing to do with server side objects.

    Monday, October 06, 2008 6:00 AM

All replies

  • Please remember that No ISerializable, XmlElement, Array of type XmlNode or IXmlSerializable types can be used in Silverlight 2.0 data contracts.

    Serialization in Silverlight is supported only through DataContract, DataContractJSON or XML. You need to add DataContractAttribute to the member to indicate that they are to be serialized. You may go through following link to resolve this issue:

    http://msdn.microsoft.com/en-us/library/cc197951(VS.95).aspx

     

    Please mark the post as 'Answered' if this Answers your question.

     

    Friday, October 03, 2008 4:52 AM
  •  Thank you for responding. I do not see anywhere in the msdn documentation that there is any serialization associated with PropertyChangedEventHandler or PropertyChangedEventArgs. Further, here is the code snippet from the tutorial on the silverlight website at http://silverlight.net/learn/tutorials/databinding.aspx using the PropertyChangedEventHander:

     public class Book : INotifyPropertyChanged

     {

         private string bookTitle;

     

         public event PropertyChangedEventHandler PropertyChanged;

     

         public string Title

         {

             get { return bookTitle; }

             set

             {

                 bookTitle = value;

                 if ( PropertyChanged != null )

                 {

                    PropertyChanged(this, new PropertyChangedEventArgs(“Title”);

                 }

             }      

         }       

    }  

     This is not really any different than my code (accept that I didn't even get as far as implementing the event in my properties):

     

    Imports System.ComponentModel


    <Serializable()> _
    Public Class SimpleClass
        Implements INotifyPropertyChanged

        Public Event ObjectPropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged

        Private _firstName As String
        Private _lastName As String
        Private _birthDate As Date

        Public Property FirstName() As String
            Get
                Return _firstName
            End Get
            Set(ByVal value As String)
                _firstName = value
            End Set
        End Property

        Public Property LastName() As String
            Get
                Return _lastName
            End Get
            Set(ByVal value As String)
                _lastName = value
            End Set
        End Property

        Public Property BirthDate() As Date
            Get
                Return _birthDate
            End Get
            Set(ByVal value As Date)
                _birthDate = value
            End Set
        End Property

        'Tried the declaration both ways...
        ' Public Event ObjectPropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged
    End Class
     

     Adding the DataContract and DataMember attributes from System.Runtime.Serialization does not help because I get a compiler error when I add either attribute to the event declaration ("...the attribute is not valid on this declaration type").This class works fine if I remove the INotifyPropertyChanged interface and the event handler.

     Cheers, 

    D

    Friday, October 03, 2008 10:35 AM
  • Hello, are you trying to implement INotifyPropertyChanged on the server side? This will not work. INotifyPropertyChanged should be used on the client side only. It's used purely for client side data binding. WCF knows nothing about your client application's data binding. After all why it cares? If a property is changed on the client, when you call a web service, you passing the updated object as a parameter, and the service will automatically get the updated object. You implement INotifyPropertyChanged when, say, you have a ListBoxItem and a ContentControl bound to the same item. You modify a property in the source item with a TextBox in the ContentControl, and you want the ListBoxItem to update automatically. Other than such scenarios, you don't need this interface.

    I wonder if you want the object on the server side to be updated automatically together with the client object. If so, I think you have some misunderstanding with web services. In a web service's data contract, you have to keep your object model as simple as possible. Web service is very different from traditional technologies. Server and client communicates in the xml format. So everything must be able to be serialized by xml. Also web services work in a stateless model. Modifying an object on the client will not affect the server at all, no matter what interface you implement. Actually the instance of object on the client is completely different from the instance on the server. The client object may be a .NET object, while the server one may be a Java object. To get the updated object to the server, you have to call a service method. Under the hook, the client object will be serialized to an xml file, sent to the server, and then deserialized to a server object.

    This model have a lot of benefits. Most of all, now client and server are loosely coupled. If you're not accustomed to this model, then please don't use SOA. Silverlight works best with the service oriented architecture. So that means Silverlight is not the proper technology for you... But why not continue using Windows Forms while it serves you well? Unless you want your application to run cross platform, and requires extremely rich content, I don't see much benefits in Silverlight. Windows Forms serves very well for most business applications where you simply need to display data in a DataGrid, and update data in database.

    Anyway, if your company decides to adopt SOA (which is a world trend), sooner or later you'll have to be accustomed with the web service model, no matter whether you want to use Silverlight or not...

    Finally, if you create a normal DataContract in a WCF service, and add a service reference in your Silverlight application, you'll notice the generated classes all implement INotifyPropertyChanged automatically. We know this interface is very important in data binding, so the service reference tool generate it automatically. But once again, please understand this has nothing to do with server side objects.

    Monday, October 06, 2008 6:00 AM
  • Thank you for the posting. I do understand SOA, but I think I mis-understood what WCF could do for me. I thought that I could implement a class library and WCF would simply move my classes back and forth between the various parts of the architecture. 

    We have created an advanced persistence model whereby we simply pass an object to the factory layer and the system checks a dirty flag on all the sub-objects and decides if it needs to be updated. We used the INotifyPropertyChanged interface because it did work with various .net user controls (i.e. listboxes etc).

    The idea in a Windows model was that we create the objects and when we are done modifying them, we simply call Factory.Save(object) and everything is persisted (according to the dirty flags). I thought that with WCF we would pass the same object to a Silverlight application, and when complete, pass the object back to the server and call the Factory.Save(object) function again. This does not mean keeping things in sync. I understand stateless models, but what I did think is that WCF was able to "transfer" my objects from one place to another much like Remoting or DCOM.

    Anyway, thanks again.

    Monday, October 06, 2008 10:36 AM