DXSerializer Events - Advanced Scenarios
- 7 minutes to read
This topic describes advanced use cases of the DXSerializer‘s events.
Serialize/Deserialize Custom Properties of a DevExpress WPF Control Descendant
Requirements that Custom Properties Must Meet to be Saved/Restored
Mark the property with the
[XtraSerializableProperty]
attribute.In the GridControl‘s descendants, you should also assign one of the following attributes to the property:
- The
[GridUIProperty]
attribute to save/restore a custom property when the DXSerializer.StoreLayoutMode is UI. - The
[GridStoreAlwaysProperty]
attribute to save/restore a custom property when the DXSerializer.StoreLayoutMode is None.
- The
If your property is a dependency property, specify its local value.
Example
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);
}
}
Serialize Custom Attached Properties
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);
}
Serialize Standard and Custom Controls
To save/restore properties of custom and standard controls, do the following:
- Specify the SerializationID property for a control whose layout you want to save/restore.
- Mark the control’s properties whose values you want to save/restore with the
[XtraSerializableProperty]
attribute. - Do one of the following:
- Pass properties to the DXSerializer.AddCustomGetSerializablePropertiesHandler method.
- Handle the CustomGetSerializableProperties event and pass properties to the CustomGetSerializablePropertiesEventArgs.SetPropertySerializable method.
Do not Restore a Control’s Predefined Property
Do the following to prevent a property from deserialization:
- Handle the AllowProperty event.
- Set the AllowPropertyEventArgs.Allow property to
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;
}
}
Stop Layout Restore (Deserialization)
- Handle the BeforeLoadLayout event.
- Set the BeforeLoadLayoutEventArgs.Allow event argument to
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;
}
}
}
Restore Items From a Saved (Serialized) Collection
- Handle the CreateCollectionItem event.
- Create an instance of the collection object that you want to restore.
- Add the created instance to the e.Collection event argument.
- Set the e.CollectionItem to the created object’s instance.
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;
}
}
}
Save Controls that do not Exist in the Visual Tree
- Handle the CustomGetSerializableChildren event.
- Add a control whose layout you want to save to the CustomGetSerializableChildrenEventArgs.Children collection.
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);
}
}
Serialize Properties that are not Marked with the XtraSerializablePropertyAttribute
- Handle the CustomGetSerializableProperties event.
- Pass the property whose value you want to save/restore to the CustomGetSerializablePropertiesEventArgs.SetPropertySerializable method.
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() { });
}
}
Update Layout Between Different Versions of Your Application
Do the following to update your application’s layout in a newer application version:
- Specify or increment the DXSerializer.LayoutVersion attached property value. This property is the version of your application’s layout.
- Change your application’s layout.
- If the DXSerializer.LayoutVersion attached property value of your application is lower than the new property value, the LayoutUpgrade event is fired.
Note
The DXSerializer.AddXXXHandler methods work only for UIElements. If an element is a FrameworkContentElement descendant, use the standard AddHandler method.
Create a Custom Property Deserialization Handler
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>