DXSerializer事件-高級(jí)場(chǎng)景
本主題描述DXSerializer事件的高級(jí)用例。
序列化/反序列化DevExpress WPF控件子類的自定義屬性
保存/恢復(fù)自定義屬性必須滿足的要求
1.用[XtraSerializableProperty]屬性標(biāo)記屬性。
在GridControl的后代中,您還應(yīng)該為該屬性分配以下屬性之一:
- 當(dāng)DXSerializer.StoreLayoutMode為UI時(shí),[GridUIProperty]屬性用于保存/恢復(fù)自定義屬性。
- 當(dāng)DXSerializer.StoreLayoutMode為None時(shí),[GridStoreAlwaysProperty]屬性用于保存/恢復(fù)自定義屬性。
2.如果屬性是依賴屬性,請(qǐng)指定其本地值。
下面的代碼示例保存/恢復(fù)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
序列化自定義附加屬性
要序列化自定義附加屬性,請(qǐng)使用[xtrasserializableproperty]屬性標(biāo)記該屬性的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
序列化標(biāo)準(zhǔn)和自定義控件
要保存/恢復(fù)自定義控件和標(biāo)準(zhǔn)控件的屬性,請(qǐng)執(zhí)行以下操作:
1.為要保存/恢復(fù)其布局的控件指定SerializationID屬性。
2.用[XtraSerializableProperty]屬性標(biāo)記要保存/恢復(fù)其值的控件屬性。
3.做以下其中一件事:
將屬性傳遞給DXSerializer.AddCustomGetSerializablePropertiesHandler方法。
處理CustomGetSerializableProperties事件并將屬性傳遞給CustomGetSerializablePropertiesEventArgs.SetPropertySerializable方法。
不恢復(fù)控件的預(yù)定義屬性
執(zhí)行以下操作來(lái)防止屬性反序列化:
1.處理AllowProperty事件。
2.設(shè)置AllowPropertyEventArgs,允許屬性為false。
您可以使用AllowPropertyEventArgs.Property來(lái)獲得一個(gè)反序列化的屬性。
下面的代碼示例禁用了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
停止布局恢復(fù)(反序列化)
1.處理BeforeLoadLayout事件。
2.將BeforeLoadLayoutEventArgs.Allow事件參數(shù)設(shè)置為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
從已保存(序列化)集合恢復(fù)項(xiàng)
- 處理CreateCollectionItem事件。
- 創(chuàng)建要恢復(fù)的集合對(duì)象的實(shí)例。
- 將創(chuàng)建的實(shí)例添加到e.Collection事件參數(shù)中。
- 設(shè)置e.CollectionItem為創(chuàng)建對(duì)象的實(shí)例。
例如,GridControl處理此事件來(lái)恢復(fù)列、摘要項(xiàng)、MRU過(guò)濾器等。
如果屬性被標(biāo)記為[xtrasserialableproperty]屬性,則引發(fā)此事件,XtraSerializableProperty.XtraSerializationVisibility屬性必須設(shè)置為xXtraSerializationVisibility.Collection,XtraSerializableProperty.UseCreateItem屬性應(yīng)該設(shè)置為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
保存可視樹(shù)中不存在的控件
處理CustomGetSerializableChildren事件。
添加一個(gè)控件,它的布局要保存到CustomGetSerializableChildrenEventArgs.Children集合。
如果一個(gè)LayoutPanel包含一個(gè)UserControl和一個(gè)GridControl,并且這個(gè)面板沒(méi)有被激活,GridControl在可視樹(shù)中不存在,并且它的屬性沒(méi)有被保存(序列化)。要保存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
序列化沒(méi)有被xtrasserializable屬性標(biāo)記的屬性
1.處理CustomGetSerializableProperties事件。
2.將要保存/恢復(fù)其值的屬性傳遞給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
在應(yīng)用程序的不同版本之間更新布局
執(zhí)行以下操作并在較新的應(yīng)用程序版本中更新應(yīng)用程序的布局:
1.指定或增加DXSerializer.LayoutVersion附加的屬性值,此屬性是應(yīng)用程序布局的版本。
2.更改應(yīng)用程序的布局。
3.如果應(yīng)用程序的DXSerializer.LayoutVersion附加屬性值低于新屬性值,則觸發(fā)LayoutUpgrade事件。
提示:DXSerializer.AddXXXHandler方法只適用于UI元素。如果一個(gè)元素是FrameworkContentElement的后代,則使用標(biāo)準(zhǔn)的AddHandler方法。
創(chuàng)建自定義屬性反序列化處理程序
當(dāng)屬性被反序列化時(shí),將發(fā)生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