DXSerializer事件-高級場景
本主題描述DXSerializer事件的高級用例。
序列化/反序列化DevExpress WPF控件子類的自定義屬性
保存/恢復自定義屬性必須滿足的要求
1.用[XtraSerializableProperty]屬性標記屬性。
在GridControl的后代中,您還應該為該屬性分配以下屬性之一:
- 當DXSerializer.StoreLayoutMode為UI時,[GridUIProperty]屬性用于保存/恢復自定義屬性。
- 當DXSerializer.StoreLayoutMode為None時,[GridStoreAlwaysProperty]屬性用于保存/恢復自定義屬性。
2.如果屬性是依賴屬性,請指定其本地值。
下面的代碼示例保存/恢復MyCustomProperty依賴屬性值:
XAML:
<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>
C# :
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); } }
VB.NET:
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
序列化自定義附加屬性
要序列化自定義附加屬性,請使用[xtrasserializableproperty]屬性標記該屬性的Get方法。
C# :
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); }
VB.NET:
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
序列化標準和自定義控件
要保存/恢復自定義控件和標準控件的屬性,請執行以下操作:
1.為要保存/恢復其布局的控件指定SerializationID屬性。
2.用[XtraSerializableProperty]屬性標記要保存/恢復其值的控件屬性。
3.做以下其中一件事:
將屬性傳遞給DXSerializer.AddCustomGetSerializablePropertiesHandler方法。
處理CustomGetSerializableProperties事件并將屬性傳遞給CustomGetSerializablePropertiesEventArgs.SetPropertySerializable方法。
不恢復控件的預定義屬性
執行以下操作來防止屬性反序列化:
1.處理AllowProperty事件。
2.設置AllowPropertyEventArgs,允許屬性為false。
您可以使用AllowPropertyEventArgs.Property來獲得一個反序列化的屬性。
下面的代碼示例禁用了GridControl列的WidthProperty的反序列化操作:
MainWindow.xaml.cs:
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; } }
MainWindow.xaml.vb:
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
停止布局恢復(反序列化)
1.處理BeforeLoadLayout事件。
2.將BeforeLoadLayoutEventArgs.Allow事件參數設置為false。
下面的代碼示例禁用GridControl的屬性反序列化,如果布局版本不是1.48:
MainWindow.xaml.cs:
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; } } }
MainWindow.xaml.vb:
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
從已保存(序列化)集合恢復項
- 處理CreateCollectionItem事件。
- 創建要恢復的集合對象的實例。
- 將創建的實例添加到e.Collection事件參數中。
- 設置e.CollectionItem為創建對象的實例。
例如,GridControl處理此事件來恢復列、摘要項、MRU過濾器等。
如果屬性被標記為[xtrasserialableproperty]屬性,則引發此事件,XtraSerializableProperty.XtraSerializationVisibility屬性必須設置為xXtraSerializationVisibility.Collection,XtraSerializableProperty.UseCreateItem屬性應該設置為true。
C# :
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; } } }
VB.NET:
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
保存可視樹中不存在的控件
處理CustomGetSerializableChildren事件。
添加一個控件,它的布局要保存到CustomGetSerializableChildrenEventArgs.Children集合。
如果一個LayoutPanel包含一個UserControl和一個GridControl,并且這個面板沒有被激活,GridControl在可視樹中不存在,并且它的屬性沒有被保存(序列化)。要保存GridControl的屬性,將GridControl添加到CustomGetSerializableChildrenEventArgs.Children集合中。
MainWindow.xaml.cs:
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); } }
MainWindow.xaml.vb:
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
序列化沒有被xtrasserializable屬性標記的屬性
1.處理CustomGetSerializableProperties事件。
2.將要保存/恢復其值的屬性傳遞給CustomGetSerializablePropertiesEventArgs.SetPropertySerializable方法。
下面的代碼示例保存(序列化)GridColumn.Tag屬性:
C# :
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() { }); } }
VB.NET:
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
在應用程序的不同版本之間更新布局
執行以下操作并在較新的應用程序版本中更新應用程序的布局:
1.指定或增加DXSerializer.LayoutVersion附加的屬性值,此屬性是應用程序布局的版本。
2.更改應用程序的布局。
3.如果應用程序的DXSerializer.LayoutVersion附加屬性值低于新屬性值,則觸發LayoutUpgrade事件。
提示:DXSerializer.AddXXXHandler方法只適用于UI元素。如果一個元素是FrameworkContentElement的后代,則使用標準的AddHandler方法。
創建自定義屬性反序列化處理程序
當屬性被反序列化時,將發生DeserializeProperty事件,您可以使用XtraPropertyInfoEventArgs.Name/XtraPropertyInfoEventArgs.DependencyProperty獲取屬性/依賴屬性的名稱。
XAML:
<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>
C# :
private void grid_DeserializeProperty(object sender, DevExpress.Xpf.Core.Serialization.XtraPropertyInfoEventArgs e) { if (e.DependencyProperty == ColumnBase.VisibleProperty) { e.Handled = true; // ... } }
VB.NET:
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