wpf-7410-common-concepts-saving-and-restoring-layouts-advanced-scenarios.md
This topic describes advanced use cases of the DXSerializer‘s events.
Mark the property with the [XtraSerializableProperty] attribute.
If your property is a dependency property, specify its local value.
The following code sample saves/restores the MyCustomProperty dependency property value:
<Window
xmlns:dx="http://schemas.devexpress.com/winfx/2008/xaml/core"
xmlns:local="clr-namespace:GridSerialization"
xmlns:dxg="http://schemas.devexpress.com/winfx/2008/xaml/grid"
x:Class="GridSerialization.MainWindow">
<StackPanel>
<local:GridControlEx dx:DXSerializer.StoreLayoutMode="UI" x:Name="grid" MyCustomProperty="15">
<dxg:GridControl.View>
<dxg:TableView/>
</dxg:GridControl.View>
</local:GridControlEx>
</StackPanel>
</Window>
using DevExpress.Utils.Serializing;
using DevExpress.Xpf.Grid;
using DevExpress.Xpf.Core.Serialization;
public class GridControlEx : GridControl {
public static DependencyProperty MyCustomPropertyProperty =
DependencyProperty.Register("MyCustomProperty", typeof(int), typeof(GridControlEx));
[XtraSerializableProperty]
[GridStoreAlwaysProperty]
public int MyCustomProperty {
get => (int)GetValue(MyCustomPropertyProperty);
set => SetValue(MyCustomPropertyProperty, value);
}
}
Imports DevExpress.Utils.Serializing
Imports DevExpress.Xpf.Grid
Imports DevExpress.Xpf.Core.Serialization
Public Class GridControlEx
Inherits GridControl
Public Shared MyCustomPropertyProperty As DependencyProperty = DependencyProperty.Register("MyCustomProperty", GetType(Integer), GetType(GridControlEx))
<XtraSerializableProperty>
<GridStoreAlwaysProperty>
Public Property MyCustomProperty As Integer
Get
Return CInt(GetValue(MyCustomPropertyProperty))
End Get
Set(ByVal value As Integer)
Return SetValue(MyCustomPropertyProperty, value)
End Set
End Property
End Class
To serialize a custom attached property, mark the property’s Get method with the [XtraSerializableProperty] attribute.
public static readonly DependencyProperty IsCheckedProperty =
DependencyProperty.RegisterAttached("IsChecked", typeof(bool), typeof(GridControlEx), new PropertyMetadata(false));
[XtraSerializableProperty]
public static bool GetIsChecked(DependencyObject obj) {
return (bool)obj.GetValue(IsCheckedProperty);
}
public static void SetIsChecked(DependencyObject obj, bool value) {
obj.SetValue(IsCheckedProperty, value);
}
Public Shared ReadOnly IsCheckedProperty As DependencyProperty = DependencyProperty.RegisterAttached("IsChecked", GetType(Boolean), GetType(GridControlEx), New PropertyMetadata(False))
<XtraSerializableProperty>
Public Shared Function GetIsChecked(ByVal obj As DependencyObject) As Boolean
Return CBool(obj.GetValue(IsCheckedProperty))
End Function
Public Shared Sub SetIsChecked(ByVal obj As DependencyObject, ByVal value As Boolean)
obj.SetValue(IsCheckedProperty, value)
End Sub
To save/restore properties of custom and standard controls, do the following:
[XtraSerializableProperty] attribute.Do the following to prevent a property from deserialization:
false.You can use AllowPropertyEventArgs.Property to get a deserialized property.
The following code sample disables the deserialization operation for the GridControl column’s WidthProperty:
using DevExpress.Xpf.Core.Serialization;
using DevExpress.Xpf.Grid;
// ...
public partial class MainWindow : Window {
public MainWindow() {
//...
grid.Columns[nameof(Customer.ID)].AddHandler(DXSerializer.AllowPropertyEvent,
new AllowPropertyEventHandler(OnAllowProperty));
}
void OnAllowProperty(object sender, AllowPropertyEventArgs e) {
if (e.DependencyProperty == GridColumn.WidthProperty)
e.Allow = false;
}
}
Imports DevExpress.Xpf.Core.Serialization
Imports DevExpress.Xpf.Grid
'...
Public Partial Class MainWindow
Inherits Window
Public Sub New()
' ...
grid.Columns(NameOf(Customer.ID)).[AddHandler](DXSerializer.AllowPropertyEvent,
New AllowPropertyEventHandler(AddressOf OnAllowProperty))
End Sub
Private Sub OnAllowProperty(ByVal sender As Object, ByVal e As AllowPropertyEventArgs)
If e.DependencyProperty = GridColumn.WidthProperty Then e.Allow = False
End Sub
End Class
View Example: Do not serialize a GridControl's properties
false.The following code sample disables the GridControl‘s property deserialization if the layout version is not 1.48:
using DevExpress.Utils.Serializing;
using DevExpress.Xpf.Core.Serialization;
using DevExpress.Xpf.Grid;
using DevExpress.Xpf.Core;
// ...
public partial class MainWindow : Window {
public MainWindow() {
//...
grid.AddHandler(DXSerializer.BeforeLoadLayoutEvent, new BeforeLoadLayoutEventHandler(BeforeLoadLayoutHandler));
}
void BeforeLoadLayoutHandler(object sender, BeforeLoadLayoutEventArgs e) {
if (e.RestoredVersion != "1.48") {
e.Allow = false;
}
}
}
Imports DevExpress.Utils.Serializing
Imports DevExpress.Xpf.Core.Serialization
Imports DevExpress.Xpf.Grid
Imports DevExpress.Xpf.Core
'...
Public Partial Class MainWindow
Inherits Window
Public Sub New()
InitializeComponent()
Me.DataContext = Me
grid.[AddHandler](DXSerializer.BeforeLoadLayoutEvent, New BeforeLoadLayoutEventHandler(AddressOf BeforeLoadLayoutHandler))
End Sub
Sub BeforeLoadLayoutHandler(ByVal sender As Object, ByVal e As BeforeLoadLayoutEventArgs)
e.Allow = False
End Sub
End Class
For example, the GridControl handles this event to restore columns, summary items, MRU filters, and so on.
This event is raised if a property is marked with the [XtraSerializableProperty] attribute. The XtraSerializableProperty.XtraSerializationVisibility property must be set to XtraSerializationVisibility.Collection and the XtraSerializableProperty.UseCreateItem property should be set to true.
using DevExpress.Utils.Serializing;
using DevExpress.Xpf.Core.Serialization;
using DevExpress.Xpf.Grid;
using DevExpress.Xpf.Core;
// ...
public partial class MainWindow : Window {
public MainWindow() {
//...
grid.Columns["Name"].AddHandler(DXSerializer.CreateCollectionItemEvent, new XtraCreateCollectionItemEventHandler(OnCreateCollectionItem));
}
void OnCreateCollectionItem(object sender, XtraCreateCollectionItemEventArgs e) {
if (e.CollectionName == nameof(MyGridColumn.SomeCollection)) {
CustomObject item = new CustomObject();
((ObservableCollection<CustomObject>)e.Collection).Add(item);
e.CollectionItem = item;
}
}
public class MyGridColumn : GridColumn {
[XtraSerializableProperty(XtraSerializationVisibility.Collection, true, false, true)]
public ObservableCollection<CustomObject> SomeCollection {
get { return (ObservableCollection<CustomObject>)GetValue(SomeCollectionProperty); }
set { SetValue(SomeCollectionProperty, value); }
}
public static readonly DependencyProperty SomeCollectionProperty = DependencyProperty.Register("SomeCollection", typeof(ObservableCollection<CustomObject>), typeof(MyGridColumn), null);
}
public class CustomObject : INotifyPropertyChanged {
string itemID;
string itemValue;
[XtraSerializableProperty]
public string ItemID {
get {
return itemID;
}
set {
itemID = value;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("ItemID"));
}
}
[XtraSerializableProperty]
public string ItemValue {
get {
return itemValue;
}
set {
itemValue = value;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("PropertyB"));
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string propertyName) {
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public class Customer {
public int ID {
get;
set;
}
public string Name {
get;
set;
}
}
}
Imports DevExpress.Utils.Serializing
Imports DevExpress.Xpf.Core.Serialization
Imports DevExpress.Xpf.Grid
Imports DevExpress.Xpf.Core
Public Partial Class MainWindow
Inherits Window
Public Sub New()
grid.Columns("Name").[AddHandler](DXSerializer.CreateCollectionItemEvent, New XtraCreateCollectionItemEventHandler(AddressOf OnCreateCollectionItem))
End Sub
Private Sub OnCreateCollectionItem(ByVal sender As Object, ByVal e As XtraCreateCollectionItemEventArgs)
Dim item As CustomObject = New CustomObject()
(CType(e.Collection, ObservableCollection(Of CustomObject))).Add(item)
e.CollectionItem = item
End Sub
End Class
If a LayoutPanel contains a UserControl with a GridControl and this panel is not activated, the GridControl does not exist in the visual tree and its properties are not saved (serialized). To save a GridControl‘s properties, add the GridControl to the CustomGetSerializableChildrenEventArgs.Children collection.
using DevExpress.Utils.Serializing;
using DevExpress.Xpf.Core.Serialization;
using DevExpress.Xpf.Grid;
using DevExpress.Xpf.Core;
using DevExpress.Xpf.Docking;
// ...
public partial class MainWindow : Window {
public MainWindow() {
//...
layoutPanel.AddHandler(DXSerializer.CustomGetSerializableChildrenEvent, new CustomGetSerializableChildrenEventHandler(CustomGetSerializableChildrenEventHandler));
}
///...
void OnCreateContentPropertyValue(object sender, XtraCreateContentPropertyValueEventArgs e) {
e.Children.Add(grid);
}
}
Imports DevExpress.Utils.Serializing
Imports DevExpress.Xpf.Core.Serialization
Imports DevExpress.Xpf.Grid
Imports DevExpress.Xpf.Core
Imports DevExpress.Xpf.Docking
'...
Public Partial Class MainWindow
Inherits Window
Public Sub New()
'...
layoutPanel.[AddHandler](DXSerializer.CustomGetSerializableChildrenEvent, New CustomGetSerializableChildrenEventHandler(CustomGetSerializableChildrenEventHandler))
End Sub
'...
Sub OnCreateContentPropertyValue(ByVal sender As Object, ByVal e As XtraCreateContentPropertyValueEventArgs)
e.Children.Add(grid)
End Sub
End Class
The following code sample saves (serializes) the GridColumn.Tag property:
using DevExpress.Utils.Serializing;
using DevExpress.Xpf.Core.Serialization;
using DevExpress.Xpf.Grid;
using DevExpress.Xpf.Core;
//...
public partial class MainWindow : Window {
public MainWindow() {
//...
grid.AddHandler(DXSerializer.CustomGetSerializablePropertiesEvent, new CustomGetSerializablePropertiesEventHandler(CustomGetSerializablePropertiesHandler));
}
void CustomGetSerializablePropertiesHandler(object sender, CustomGetSerializablePropertiesEventArgs e) {
e.SetPropertySerializable(GridColumn.TagProperty, new DXSerializable() { });
}
}
Imports DevExpress.Utils.Serializing
Imports DevExpress.Xpf.Core.Serialization
Imports DevExpress.Xpf.Grid
Imports DevExpress.Xpf.Core
'...
Public Partial Class MainWindow
Inherits Window
Public Sub New()
InitializeComponent()
Me.DataContext = Me
grid.[AddHandler](DXSerializer.CustomGetSerializablePropertiesEvent, New CustomGetSerializablePropertiesEventHandler(CustomGetSerializablePropertiesHandler))
End Sub
Sub CustomGetSerializablePropertiesHandler(ByVal sender As Object, ByVal e As CustomGetSerializablePropertiesEventArgs)
e.SetPropertySerializable(GridColumn.TagProperty, New DXSerializable())
End Sub
End Class
Do the following to update your application’s layout in a newer application version:
View Example: How to use the LayoutUpgrade event to upgrade a layout from one version to another
Note
The DXSerializer.AddXXXHandler methods work only for UIElements. If an element is a FrameworkContentElement descendant, use the standard AddHandler method.
The DeserializeProperty event occurs when a property is deserialized. You can use XtraPropertyInfoEventArgs.Name/XtraPropertyInfoEventArgs.DependencyProperty to get a name of a property/dependency property.
<Window ...
xmlns:dx="http://schemas.devexpress.com/winfx/2008/xaml/core"
xmlns:dxg="http://schemas.devexpress.com/winfx/2008/xaml/grid">
<DockPanel>
<!-- ... -->
<dxg:GridControl x:Name="grid" dx:DXSerializer.DeserializeProperty="grid_DeserializeProperty">
<!-- ... -->
</dxg:GridControl>
</DockPanel>
</Window>
private void grid_DeserializeProperty(object sender, DevExpress.Xpf.Core.Serialization.XtraPropertyInfoEventArgs e) {
if (e.DependencyProperty == ColumnBase.VisibleProperty) {
e.Handled = true;
// ...
}
}
Private Sub grid_DeserializeProperty(ByVal sender As Object, ByVal e As DevExpress.Xpf.Core.Serialization.XtraPropertyInfoEventArgs)
If e.DependencyProperty = ColumnBase.VisibleProperty Then
e.Handled = True
'...
End If
End Sub