Back to Devexpress

LayoutSerializationService

wpf-114419-mvvm-framework-services-predefined-set-layoutserializationservice.md

latest20.3 KB
Original Source

LayoutSerializationService

  • Jan 20, 2023
  • 7 minutes to read

LayoutSerializationService is an ILayoutSerializationService implementation that allows you to save/restore layout of serializable DevExpress WPF Controls located on a View.(i.e., DXGrid , DXPivotGrid , DXDocking , DXBars and DXLayoutControl ).

Getting Started with the LayoutSerializationService

To save/restore a layout of your View and its child element, add the LayoutSerializationService to the View’s Interaction.Behaviors collection.

xaml
<UserControl x:Class="LayoutSerializationService.Views.MainView"
    ...
    xmlns:dxmvvm="http://schemas.devexpress.com/winfx/2008/xaml/mvvm" 
    xmlns:ViewModels="clr-namespace:LayoutSerializationService.ViewModels"
    DataContext="{dxmvvm:ViewModelSource Type=ViewModels:MainViewModel}">
    ...
    <dxmvvm:Interaction.Behaviors>
        <dxmvvm:LayoutSerializationService />
    </dxmvvm:Interaction.Behaviors>
    ...
</UserControl>

Refer to the following help topic for more information: Add Behaviors in XAML.

Then, use one of the following ways to access the defined service.

Next, call the service’s Serialize/Deserialize method to save/restore the View’s layout respectively. The Serialize method returns a string object that contains layout settings that you can restore by using the Deserialize method in the sequel. To restore a specific layout, pass the corresponding string object to the Deserialize method using its parameter.

When the Serialize/Deserialize method is invoked, the LayoutSerializationService iterates through visual tree elements and saves/restores the layout of controls supporting serialization and their child elements by using the DXSerializer methods. Therefore, to properly perform serialization and deserialization, follow the recommendations described in the Save/Restore Control Layout topic.

Tip

If you use LayoutSerializationService in conjunction with CurrentWindowSerializationBehavior, use the Initialized event to deserialize the layout on the application startup. Otherwise, the window may flicker during the deserialization.

Serialization Capabilities

To prevent a specific control and its child elements from being serialized/deserialized, set the DXSerializer.Enabled attached property to false for this control.

Example

View Example

csharp
using System;
using DevExpress.Mvvm.DataAnnotations;
using DevExpress.Mvvm;
using DevExpress.Mvvm.POCO;
using DocumentManagerSerialization.Properties;
using System.Collections.Generic;
using DocumentManagerSerialization.Common;

namespace DocumentManagerSerialization.ViewModels {
    [POCOViewModel]
    public class MainViewModel : ISupportLogicalLayout {

        public IDocumentManagerService DocumentManagerService { get { return this.GetService<IDocumentManagerService>(); } }
        public ILayoutSerializationService LayoutSerializationService { get { return this.GetService<ILayoutSerializationService>(); } }
        public virtual ViewModelState State { get; set; }

        public MainViewModel() {
            State = new ViewModelState() { State = "I'm Root!" };
        }

        [Command]
        public void OnWindowClosing() {
            Settings.Default.LogicalLayout = this.SerializeDocumentManagerService();
            Settings.Default.RootLayout = LayoutSerializationService.Serialize();
            Settings.Default.Save();
        }

        [Command]
        public void OnWindowLoaded() {
            if (Settings.Default.LogicalLayout != null) {
                this.RestoreDocumentManagerService(Settings.Default.LogicalLayout);
            }
            if (Settings.Default.RootLayout != null) {
                LayoutSerializationService.Deserialize(Settings.Default.RootLayout);
            }
        }

        [Command]
        public void OpenDocument() {
            var document = DocumentManagerService.CreateDocument("DocumentView", null, this);
            document.Id = "Document" + Guid.NewGuid().ToString().Replace("-", "");
            document.DestroyOnClose = false;
            document.Title = "Root Document";
            document.Show();
        }

        #region ISupportLogicalLayout
        public bool CanSerialize {
            get { return true; }
        }

        public IEnumerable<object> LookupViewModels {
            get { return null; }
        }
        #endregion
    }
}
csharp
using System;
using DevExpress.Mvvm.DataAnnotations;
using DevExpress.Mvvm;
using DevExpress.Mvvm.POCO;
using System.Collections.Generic;
using DocumentManagerSerialization.Common;

namespace DocumentManagerSerialization.ViewModels {
    [POCOViewModel]
    public class DocumentViewModel : ISupportLogicalLayout<ViewModelState>, ISupportParentViewModel, IDocumentContent {

        public IDocumentManagerService DocumentManagerService { get { return this.GetService<IDocumentManagerService>(); } }

        public virtual string Caption { get; set; }
        public virtual bool CanBeClosed { get; set; }
        public virtual ViewModelState State { get; set; }

        public DocumentViewModel() {
            State = new ViewModelState() { State = "Default State" };
        }

        public void OpenChildDocument() {
            var document = DocumentManagerService.CreateDocument("DocumentView", null, this);
            document.DestroyOnClose = false;
            document.Title = "Child Document";
            document.Id = "Child" + Guid.NewGuid().ToString().Replace("-", "");
            document.Show();
        }

        public ViewModelState SaveState() {
            return State;
        }

        public void RestoreState(ViewModelState state) {
            State = state;
        }

        #region ISupportLogicalLayout

        bool ISupportLogicalLayout.CanSerialize {
            get { return !String.IsNullOrEmpty(State.State); }
        }

        public IEnumerable<object> LookupViewModels {
            get { return null; }
        }

        #endregion

        #region ISupportParentViewModel

        public virtual object ParentViewModel { get; set; }

        #endregion

        #region IDocumentContent

        public IDocumentOwner DocumentOwner { get; set; }

        public void OnClose(System.ComponentModel.CancelEventArgs e) {
            e.Cancel = !CanBeClosed;
        }

        public void OnDestroy() { }

        public object Title {
            get { return Caption; }
        } 

        #endregion
    }
}
xaml
<UserControl x:Class="DocumentManagerSerialization.Views.DocumentView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:dx="http://schemas.devexpress.com/winfx/2008/xaml/core"
    xmlns:dxb="http://schemas.devexpress.com/winfx/2008/xaml/bars"
    xmlns:dxe="http://schemas.devexpress.com/winfx/2008/xaml/editors"
    xmlns:dxg="http://schemas.devexpress.com/winfx/2008/xaml/grid"
    xmlns:dxmvvm="http://schemas.devexpress.com/winfx/2008/xaml/mvvm" 
    xmlns:ViewModels="clr-namespace:DocumentManagerSerialization.ViewModels"
    mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300"
    DataContext="{dxmvvm:ViewModelSource Type=ViewModels:DocumentViewModel}">
    <DockPanel>
        <dxb:ToolBarControl DockPanel.Dock="Top">
            <dxb:ToolBarControl.Items>
                <dxb:BarButtonItem Content="New Sub Document" BarItemDisplayMode="ContentAndGlyph" Glyph="{dx:DXImage Image=New_16x16.png}" Command="{Binding OpenChildDocumentCommand}"/>
                <dxb:BarEditItem Content="Document state: " EditValue="{Binding State.State, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged }">
                    <dxb:BarEditItem.EditSettings>
                        <dxe:TextEditSettings/>
                    </dxb:BarEditItem.EditSettings>
                </dxb:BarEditItem>
                <dxb:BarEditItem Content="Can be Closed" EditValue="{Binding CanBeClosed, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged }">
                    <dxb:BarEditItem.EditSettings>
                        <dxe:CheckEditSettings/>
                    </dxb:BarEditItem.EditSettings>
                </dxb:BarEditItem>
            </dxb:ToolBarControl.Items>
        </dxb:ToolBarControl>
        <dxb:StatusBarControl DockPanel.Dock="Bottom">
            <dxb:StatusBarControl.Items>
                <dxb:BarStaticItem Content="{Binding ParentViewModel.State.State}">
                    <dxb:BarStaticItem.ContentTemplate>
                        <DataTemplate>
                            <StackPanel Orientation="Horizontal">
                                <TextBlock Text="Parent's state: "/>
                                <TextBlock Text="{Binding}"/>
                            </StackPanel>
                        </DataTemplate>
                    </dxb:BarStaticItem.ContentTemplate>
                </dxb:BarStaticItem>
            </dxb:StatusBarControl.Items>
        </dxb:StatusBarControl>
        <Border>
            <TextBlock Text="Document" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="32"/>
        </Border>        
    </DockPanel>
</UserControl>
xaml
<UserControl x:Class="DocumentManagerSerialization.Views.MainView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:dxb="http://schemas.devexpress.com/winfx/2008/xaml/bars"
    xmlns:dxmvvm="http://schemas.devexpress.com/winfx/2008/xaml/mvvm"
    xmlns:dxdo="http://schemas.devexpress.com/winfx/2008/xaml/docking"
    xmlns:ViewModels="clr-namespace:DocumentManagerSerialization.ViewModels"
    mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300"
    DataContext="{dxmvvm:ViewModelSource Type=ViewModels:MainViewModel}">
    <DockPanel>
        <dxmvvm:Interaction.Behaviors>
            <dxmvvm:CurrentWindowSerializationBehavior/>
            <dxmvvm:LayoutSerializationService/>
            <dxmvvm:CurrentWindowService ClosingCommand="{Binding OnWindowClosingCommand}"/>
            <dxmvvm:EventToCommand EventName="Initialized" Command="{Binding OnWindowLoadedCommand}"/>
        </dxmvvm:Interaction.Behaviors>
        <dxb:MainMenuControl DockPanel.Dock="Top">
            <dxb:MainMenuControl.Items>
                <dxb:BarButtonItem Content="New Root Document" Command="{Binding OpenDocumentCommand}"/>
                <dxb:BarSplitButtonItem Content="Thems">
                    <dxmvvm:Interaction.Behaviors>
                        <dxb:BarSplitItemThemeSelectorBehavior/>
                    </dxmvvm:Interaction.Behaviors>
                </dxb:BarSplitButtonItem>
            </dxb:MainMenuControl.Items>
        </dxb:MainMenuControl>
        <dxdo:DockLayoutManager>
            <dxdo:LayoutGroup Caption="LayoutRoot">
                <dxdo:DocumentGroup x:Name="documentGroup" DestroyOnClosingChildren="False">
                    <dxmvvm:Interaction.Behaviors>
                        <dxdo:DockingDocumentUIService/>
                    </dxmvvm:Interaction.Behaviors>
                </dxdo:DocumentGroup>
            </dxdo:LayoutGroup>
        </dxdo:DockLayoutManager>
    </DockPanel>
</UserControl>
csharp
using DevExpress.Mvvm;

namespace DocumentManagerSerialization.Common {
    public class ViewModelState : ViewModelBase {
        public string State {
            get { return GetProperty(() => State); }
            set { SetProperty(() => State, value); }
        }
        public string FullOwnerName {
            get { return GetProperty(() => FullOwnerName); }
            set { SetProperty(() => FullOwnerName, value); }
        }
    }
}
vb
Imports DevExpress.Mvvm

Namespace DocumentManagerSerialization.Common
    Public Class ViewModelState
        Inherits ViewModelBase

        Public Property State() As String
            Get
                Return GetProperty(Function() State)
            End Get
            Set(ByVal value As String)
                SetProperty(Function() State, value)
            End Set
        End Property
        Public Property FullOwnerName() As String
            Get
                Return GetProperty(Function() FullOwnerName)
            End Get
            Set(ByVal value As String)
                SetProperty(Function() FullOwnerName, value)
            End Set
        End Property
    End Class
End Namespace
vb
Imports System
Imports DevExpress.Mvvm.DataAnnotations
Imports DevExpress.Mvvm
Imports DevExpress.Mvvm.POCO
Imports System.Collections.Generic
Imports DocumentManagerSerialization.Common

Namespace DocumentManagerSerialization.ViewModels
    <POCOViewModel> _
    Public Class DocumentViewModel
        Implements ISupportLogicalLayout(Of ViewModelState), ISupportParentViewModel, IDocumentContent

        Public ReadOnly Property DocumentManagerService() As IDocumentManagerService Implements ISupportLogicalLayout(Of DocumentManagerSerialization.Common.ViewModelState).DocumentManagerService
            Get
                Return Me.GetService(Of IDocumentManagerService)()
            End Get
        End Property

        Public Overridable Property Caption() As String
        Public Overridable Property CanBeClosed() As Boolean
        Public Overridable Property State() As ViewModelState

        Public Sub New()
            State = New ViewModelState() With {.State = "Default State"}
        End Sub

        Public Sub OpenChildDocument()
            Dim document = DocumentManagerService.CreateDocument("DocumentView", Nothing, Me)
            document.DestroyOnClose = False
            document.Title = "Child Document"
            document.Id = "Child" & Guid.NewGuid().ToString().Replace("-", "")
            document.Show()
        End Sub

#Region "ISupportLogicalLayout"
        Public Function SaveState() As ViewModelState Implements ISupportLogicalLayout(Of DocumentManagerSerialization.Common.ViewModelState).SaveState
            Return State
        End Function

        Public Sub RestoreState(ByVal state As ViewModelState) Implements ISupportLogicalLayout(Of DocumentManagerSerialization.Common.ViewModelState).RestoreState
            Me.State = state
        End Sub

        Private ReadOnly Property ISupportLogicalLayout_CanSerialize() As Boolean Implements ISupportLogicalLayout.CanSerialize
            Get
                Return Not String.IsNullOrEmpty(State.State)
            End Get
        End Property

        Public ReadOnly Property LookupViewModels() As IEnumerable(Of Object) Implements ISupportLogicalLayout.LookupViewModels
            Get
                Return Nothing
            End Get
        End Property

#End Region

        #Region "ISupportParentViewModel"

        Public Overridable Property ParentViewModel() As Object Implements ISupportParentViewModel.ParentViewModel

        #End Region

        #Region "IDocumentContent"

        Public Property DocumentOwner() As IDocumentOwner Implements IDocumentContent.DocumentOwner

        Public Sub OnClose(ByVal e As System.ComponentModel.CancelEventArgs) Implements IDocumentContent.OnClose
            e.Cancel = Not CanBeClosed
        End Sub

        Public Sub OnDestroy() Implements IDocumentContent.OnDestroy
        End Sub

        Public ReadOnly Property Title() As Object Implements IDocumentContent.Title
            Get
                Return Caption
            End Get
        End Property

        #End Region
    End Class
End Namespace
vb
Imports System
Imports DevExpress.Mvvm.DataAnnotations
Imports DevExpress.Mvvm
Imports DevExpress.Mvvm.POCO
Imports System.Collections.Generic
Imports DocumentManagerSerialization.Common

Namespace DocumentManagerSerialization.ViewModels
    <POCOViewModel> _
    Public Class MainViewModel
        Implements ISupportLogicalLayout

        Public ReadOnly Property DocumentManagerService() As IDocumentManagerService Implements ISupportLogicalLayout.DocumentManagerService
            Get
                Return Me.GetService(Of IDocumentManagerService)()
            End Get
        End Property
        Public ReadOnly Property LayoutSerializationService() As ILayoutSerializationService
            Get
                Return Me.GetService(Of ILayoutSerializationService)()
            End Get
        End Property
        Public Overridable Property State() As ViewModelState

        Public Sub New()
            State = New ViewModelState() With {.State = "I'm Root!"}
        End Sub

        <Command> _
        Public Sub OnWindowClosing()
            My.Settings.Default.LogicalLayout = Me.SerializeDocumentManagerService()
            My.Settings.Default.RootLayout = LayoutSerializationService.Serialize()
            My.Settings.Default.Save()
        End Sub

        <Command> _
        Public Sub OnWindowLoaded()
            If My.Settings.Default.LogicalLayout IsNot Nothing Then
                Me.RestoreDocumentManagerService(My.Settings.Default.LogicalLayout)
            End If
            If My.Settings.Default.RootLayout IsNot Nothing Then
                LayoutSerializationService.Deserialize(My.Settings.Default.RootLayout)
            End If
        End Sub

        <Command> _
        Public Sub OpenDocument()
            Dim document = DocumentManagerService.CreateDocument("DocumentView", Nothing, Me)
            document.Id = "Document" & Guid.NewGuid().ToString().Replace("-", "")
            document.DestroyOnClose = False
            document.Title = "Root Document"
            document.Show()
        End Sub

        #Region "ISupportLogicalLayout"
        Public ReadOnly Property CanSerialize() As Boolean Implements ISupportLogicalLayout.CanSerialize
            Get
                Return True
            End Get
        End Property

        Public ReadOnly Property LookupViewModels() As IEnumerable(Of Object) Implements ISupportLogicalLayout.LookupViewModels
            Get
                Return Nothing
            End Get
        End Property
        #End Region
    End Class
End Namespace

See Also

Save/Restore Control Layout