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.
#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>
private void grid_DeserializeProperty(object sender, DevExpress.Xpf.Core.Serialization.XtraPropertyInfoEventArgs e) {
if (e.DependencyProperty == ColumnBase.VisibleProperty) {
e.Handled = true;
// ...
}
}