Skip to main content

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

  1. Mark the property with the [XtraSerializableProperty] attribute.

    In the GridControl‘s descendants, you should also assign one of the following attributes to the property:

  2. 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:

  1. Specify the SerializationID property for a control whose layout you want to save/restore.
  2. Mark the control’s properties whose values you want to save/restore with the [XtraSerializableProperty] attribute.
  3. Do one of the following:

Do not Restore a Control’s Predefined Property

Do the following to prevent a property from deserialization:

  1. Handle the AllowProperty event.
  2. 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;
    }
}

View Example: Do not serialize a GridControl's properties

Stop Layout Restore (Deserialization)

  1. Handle the BeforeLoadLayout event.
  2. 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

  1. Handle the CreateCollectionItem event.
  2. Create an instance of the collection object that you want to restore.
  3. Add the created instance to the e.Collection event argument.
  4. 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

  1. Handle the CustomGetSerializableChildren event.
  2. 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

  1. Handle the CustomGetSerializableProperties event.
  2. 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:

  1. Specify or increment the DXSerializer.LayoutVersion attached property value. This property is the version of your application’s layout.
  2. Change your application’s layout.
  3. If the DXSerializer.LayoutVersion attached property value of your application is lower than the new property value, the LayoutUpgrade event is fired.

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.

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;
        // ...
    }
}