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:
- Deferred contents can not be saved.
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:
- 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.
- 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