65.9K
CodeProject is changing. Read more.
Home

Use Xaml.XamlServices to Serialize or Deserialize DependencyObject

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.50/5 (2 votes)

Jan 24, 2012

CPOL
viewsIcon

17180

How to use Xaml.XamlServices to serialize or deserialize a DependencyObject.

I was writing a Data Entity designer, and looking for a solution to serialize all objects (entities, models, fields, etc.) in the designer.

However, XamlWriter/XamlReader does not serialize UI objects (canvas, grid) properly. The content was lost and they did not generate object references.

Finally, I had to use XamlServices.Save/Parse.

I encountered the following two problems:

  1. Deferred contents can not be saved.
  2. Name, x:Name that were assigned or generated during serialization may cause an exception saying "Cannot register duplicate Name {0} in this scope" during deserialization.

Here is the solution:

  1. All objects should be defined by code and do not refer to any external sources (which are deferred objects). But images in resources are fine.
  2. In the root element/dependency object, a NameScope is required to hold all the names/reference IDs in the serialized contents.

For example, a NameScope was placed in the root element.

Public Class Designer
    Inherits Canvas
    Private dsNameScope As New NameScope
    Public Sub New()
        MyBase.New()
        dsNameScope.Add("root", Me)
    End Sub
End Class

Furthermore, the content/child/children can be hidden from the serializer by Shadows.

Public Class Designer
    Inherits Canvas
    Private dsNameScope As New NameScope
    Private WithEvents _Items As New System.Collections.ObjectModel.ObservableCollection(Of ModelBase)
    Public Sub New()
        MyBase.New()
        SetValue(ChildrenProperty, _Items)
        dsNameScope.Add("root", Me)
    End Sub
    Public Shadows ReadOnly Property Children As _
           System.Collections.ObjectModel.ObservableCollection(Of ModelBase)
        Get
            Return GetValue(ChildrenProperty)
        End Get
    End Property
    Public Shared ReadOnly ChildrenProperty As DependencyProperty = _
           DependencyProperty.Register("Children", _
           GetType(System.Collections.ObjectModel.ObservableCollection(Of ModelBase)), GetType(DataSet), _
           New PropertyMetadata(Nothing))
End Class