Back to Devexpress

DiagramControl.CustomSaveDocument Event

wpf-devexpress-dot-xpf-dot-diagram-dot-diagramcontrol-7ae26df4.md

latest19.1 KB
Original Source

DiagramControl.CustomSaveDocument Event

Fires when the diagram is about to be saved (when an end-user uses Save actions in the Diagram’s Ribbon menu, or when the DiagramControl.SaveFile/DiagramControl.SaveFileAs method is called). The event allows you to implement custom saving logic.

Namespace : DevExpress.Xpf.Diagram

Assembly : DevExpress.Xpf.Diagram.v25.2.dll

NuGet Package : DevExpress.Wpf.Diagram

Declaration

csharp
public event EventHandler<DiagramCustomSaveDocumentEventArgs> CustomSaveDocument
vb
Public Event CustomSaveDocument As EventHandler(Of DiagramCustomSaveDocumentEventArgs)

Event Data

The CustomSaveDocument event's data class is DevExpress.Xpf.Diagram.DiagramCustomSaveDocumentEventArgs.

Remarks

The CustomSaveDocument event fires in the following cases:

The CustomSaveDocument does not fire when saving the diagram with the DiagramControl.SaveDocument method.

Example

This example demonstrates how to open and save diagrams to a custom storage (e.g., a database) instead of a file system. In the example, the following events are used to implement this functionality:

DiagramControl.ShowingOpenDialog - This event fires before the standard Open dialog is shown and allows you to customize the dialog options or replace the standard dialog with a custom one. You can also cancel the Open operation by setting the e.Cancel parameter to true.

DiagramControl.ShowingSaveDialog - Similarly to the ShowingOpenDialog event, the ShowingSaveDialog event allows you to customize the standard Save dialog in DiagramControl or replace it with a custom one. Setting the e.Cancel parameter to true will cancel the Save operation.

DiagramControl.CustomLoadDocument - This event fires after a user selected a document in the Open dialog or the DiagramControl.DocumentSource property was set in code. The event exposes the selected document source (e.g., a document name or a file stream) through the e.DocumentSource property and allows you to implement your own loading logic. For example, you can retrieve a diagram file from a database and load it into DiagramControl using the DiagramControl.LoadDocument property (as demonstrated in the example) or populate the diagram with items manually. After implementing your custom loading logic, set the e.Handled parameter to true, so that DiagramControl does not load the previously selected document source.

DiagramControl.CustomSaveDocument - The CustomSaveDocument event allows you to specify custom saving logic for your diagram. The event fires after the Save operation was initiated and selection was made in the Save dialog (if there was a dialog). The e.DocumentSource property specifies the default location (file name, stream, etc.) where the diagram will be saved. You can set the e.Handled parameter to true to cancel the standard saving logic and implement your custom one. For example, save the diagram to a stream using the DiagramControl.SaveDocument method as demonstrated in the example or iterate through diagram items manually and read required information.

xaml
<dx:DXWindow x:Class="DXDiagram.CustomDiagramStorage.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:dx="http://schemas.devexpress.com/winfx/2008/xaml/core"
        xmlns:dxmvvm="http://schemas.devexpress.com/winfx/2008/xaml/mvvm"
        xmlns:dxb="http://schemas.devexpress.com/winfx/2008/xaml/bars"
        xmlns:dxe="http://schemas.devexpress.com/winfx/2008/xaml/editors"
        xmlns:dxdiag="http://schemas.devexpress.com/winfx/2008/xaml/diagram"
        Title="MainWindow" Height="800" Width="1400" Loaded="OnLoaded" WindowStartupLocation="CenterScreen">
    <Window.Resources>
        <Style x:Key="DialogWindowStyle" TargetType="dx:DXWindow">
            <Setter Property="WindowStyle" Value="ToolWindow"/>
            <Setter Property="Width" Value="250"/>
            <Setter Property="Height" Value="300"/>
        </Style>
    </Window.Resources>
    <dxmvvm:Interaction.Behaviors>
        <dx:DialogService Name="openDialogService" DialogWindowStartupLocation="CenterScreen" DialogStyle="{StaticResource DialogWindowStyle}">
            <dx:DialogService.ViewTemplate>
                <DataTemplate>
                    <ListBox ItemsSource="{Binding Names}" SelectedItem="{Binding SelectedName}"/>
                </DataTemplate>
            </dx:DialogService.ViewTemplate>
        </dx:DialogService>
        <dx:DialogService Name="saveDialogService" DialogWindowStartupLocation="CenterScreen" DialogStyle="{StaticResource DialogWindowStyle}">
            <dx:DialogService.ViewTemplate>
                <DataTemplate>
                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto"/>
                            <RowDefinition Height="*"/>
                        </Grid.RowDefinitions>
                        <dxe:TextEdit Text="{Binding SelectedName, UpdateSourceTrigger=PropertyChanged}"/>
                        <ListBox Grid.Row="1" ItemsSource="{Binding Names}" SelectedItem="{Binding SelectedName}"/>
                    </Grid>
                </DataTemplate>
            </dx:DialogService.ViewTemplate>
        </dx:DialogService>
    </dxmvvm:Interaction.Behaviors>
    <Grid>
        <dxdiag:DiagramDesignerControl x:Name="diagram" 
                                       SelectedStencils="BasicShapes,ArrowShapes"
                                       ShowingOpenDialog="OnShowingOpenDialog"
                                       CustomLoadDocument="OnCustomLoadDocument"
                                       ShowingSaveDialog="OnShowingSaveDialog"
                                       CustomSaveDocument="OnCustomSaveDocument"/>
    </Grid>
</dx:DXWindow>
vb
Imports DevExpress.Diagram.Core
Imports DevExpress.Xpf.Core
Imports DevExpress.Xpf.Diagram
Imports System
Imports System.Collections.Generic
Imports System.Data.Entity
Imports System.IO
Imports System.Linq
Imports System.Text
Imports System.Threading.Tasks
Imports System.Windows

Namespace DXDiagram.CustomDiagramStorage
    Friend Class DiagramStorageInitializer
        Inherits DropCreateDatabaseIfModelChanges(Of DiagramStorage)

        Protected Overrides Sub Seed(ByVal storage As DiagramStorage)
            MyBase.Seed(storage)
            Dim diagram = New DiagramControl()
            For i As Integer = 0 To 4
                diagram.Items.Add(New DiagramShape() With {.Position = New Point(200, 100 + i * 100), .Width = 100, .Height = 50, .Content = "Item " & (i + 1).ToString()})
                If i = 0 Then
                    Continue For
                End If
                Using stream = New MemoryStream()
                    diagram.SaveDocument(stream)
                    Dim diagramData = New DiagramData() With {.Name = (i + 1).ToString() & " items", .Data = stream.ToArray()}
                    storage.DiagramData.Add(diagramData)
                End Using
            Next i
            storage.SaveChanges()
        End Sub
    End Class
End Namespace
vb
Imports System
Imports System.Collections.Generic
Imports System.Data.Entity
Imports System.Linq
Imports System.Text
Imports System.Threading.Tasks

Namespace DXDiagram.CustomDiagramStorage
    Public Class DiagramStorage
        Inherits DbContext

        Public Property DiagramData() As DbSet(Of DiagramData)
    End Class
    Public Class DiagramData
        Public Property Id() As Integer
        Public Property Name() As String
        Public Property Data() As Byte()
    End Class
End Namespace
vb
Imports System
Imports System.Collections.Generic
Imports System.Linq
Imports System.Text
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Data
Imports System.Windows.Documents
Imports System.Windows.Input
Imports System.Windows.Media
Imports System.Windows.Media.Imaging
Imports System.Windows.Navigation
Imports System.Windows.Shapes
Imports DevExpress.Xpf.Core
Imports DevExpress.Diagram.Core
Imports DevExpress.Mvvm
Imports DevExpress.Mvvm.POCO
Imports System.IO

Namespace DXDiagram.CustomDiagramStorage
    ''' <summary>
    ''' Interaction logic for MainWindow.xaml
    ''' </summary>
    Partial Public Class MainWindow
        Inherits DXWindow

        Public Sub New()
            InitializeComponent()
        End Sub

        Private Sub OnLoaded(ByVal sender As Object, ByVal e As RoutedEventArgs)
            Dispatcher.BeginInvoke(New Action(AddressOf diagram.OpenFile))
        End Sub

        Private Sub OnShowingOpenDialog(ByVal sender As Object, ByVal e As DevExpress.Xpf.Diagram.DiagramShowingOpenDialogEventArgs)
            Dim viewModel = SelectDiagramViewModel.Create()
            Dim result = openDialogService.ShowDialog(MessageButton.OKCancel, "Choose a diagram to open", viewModel)
            If result = MessageResult.OK Then
                e.DocumentSourceToOpen = viewModel.SelectedName
            Else
                e.Cancel = True
            End If
        End Sub

        Private Sub OnCustomLoadDocument(ByVal sender As Object, ByVal e As DevExpress.Xpf.Diagram.DiagramCustomLoadDocumentEventArgs)
            If e.DocumentSource Is Nothing Then
                diagram.NewDocument()
                Return
            End If
            Dim storage = New DiagramStorage()
            Dim diagramInfo = storage.DiagramData.FirstOrDefault(Function(x) x.Name = CStr(e.DocumentSource))
            If diagramInfo IsNot Nothing Then
                diagram.LoadDocument(New MemoryStream(diagramInfo.Data))
            End If
            e.Handled = True
        End Sub

        Private Sub OnShowingSaveDialog(ByVal sender As Object, ByVal e As DevExpress.Xpf.Diagram.DiagramShowingSaveDialogEventArgs)
            Dim viewModel = SelectDiagramViewModel.Create()
            viewModel.SelectedName = CStr(diagram.DocumentSource)
            Dim result = saveDialogService.ShowDialog(MessageButton.OKCancel, "Choose a save location", viewModel)
            If result = MessageResult.OK Then
                e.DocumentSourceToSave = viewModel.SelectedName
            Else
                e.Cancel = True
            End If
        End Sub

        Private Sub OnCustomSaveDocument(ByVal sender As Object, ByVal e As DevExpress.Xpf.Diagram.DiagramCustomSaveDocumentEventArgs)
            Dim storage = New DiagramStorage()
            Dim diagramInfo = storage.DiagramData.FirstOrDefault(Function(x) x.Name = CStr(e.DocumentSource))
            If diagramInfo Is Nothing Then
                diagramInfo = New DiagramData() With {.Name = CStr(e.DocumentSource)}
                storage.DiagramData.Add(diagramInfo)
            End If
            Dim stream = New MemoryStream()
            diagram.SaveDocument(stream)
            diagramInfo.Data = stream.ToArray()
            storage.SaveChanges()
            e.Handled = True
        End Sub
    End Class
    Public Class SelectDiagramViewModel
        Public Shared Function Create() As SelectDiagramViewModel
            Return ViewModelSource.Create(Function() New SelectDiagramViewModel())
        End Function
        Protected Sub New()
            Dim storage = New DiagramStorage()
            Names = storage.DiagramData.Select(Function(x) x.Name).ToArray()
            SelectedName = Names.FirstOrDefault()
        End Sub
        Private privateNames As String()
        Public Property Names() As String()
            Get
                Return privateNames
            End Get
            Private Set(ByVal value As String())
                privateNames = value
            End Set
        End Property
        Public Overridable Property SelectedName() As String
    End Class
End Namespace
csharp
using DevExpress.Diagram.Core;
using DevExpress.Xpf.Core;
using DevExpress.Xpf.Diagram;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;

namespace DXDiagram.CustomDiagramStorage {
    class DiagramStorageInitializer : DropCreateDatabaseIfModelChanges<DiagramStorage> {
        protected override void Seed(DiagramStorage storage) {
            base.Seed(storage);
            var diagram = new DiagramControl();
            for(int i = 0; i < 5; i++) {
                diagram.Items.Add(new DiagramShape() {
                    Position = new Point(200, 100 + i * 100),
                    Width = 100,
                    Height = 50,
                    Content = "Item " + (i + 1).ToString(),
                });
                if(i == 0)
                    continue;
                using(var stream = new MemoryStream()) {
                    diagram.SaveDocument(stream);
                    var diagramData = new DiagramData() {
                        Name = (i + 1).ToString() + " items",
                        Data = stream.ToArray(),
                    };
                    storage.DiagramData.Add(diagramData);
                }
            }
            storage.SaveChanges();
        }
    }
}
csharp
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using DevExpress.Xpf.Core;
using DevExpress.Diagram.Core;
using DevExpress.Mvvm;
using DevExpress.Mvvm.POCO;
using System.IO;

namespace DXDiagram.CustomDiagramStorage {
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : DXWindow {
        public MainWindow() {
            InitializeComponent();
        }

        private void OnLoaded(object sender, RoutedEventArgs e) {
            Dispatcher.BeginInvoke(new Action(diagram.OpenFile));
        }

        private void OnShowingOpenDialog(object sender, DevExpress.Xpf.Diagram.DiagramShowingOpenDialogEventArgs e) {
            var viewModel = SelectDiagramViewModel.Create();
            var result = openDialogService.ShowDialog(MessageButton.OKCancel, "Choose a diagram to open", viewModel);
            if(result == MessageResult.OK)
                e.DocumentSourceToOpen = viewModel.SelectedName;
            else
                e.Cancel = true;
        }

        private void OnCustomLoadDocument(object sender, DevExpress.Xpf.Diagram.DiagramCustomLoadDocumentEventArgs e) {
            if(e.DocumentSource == null) {
                diagram.NewDocument();
                return;
            }
            var storage = new DiagramStorage();
            var diagramInfo = storage.DiagramData.FirstOrDefault(x => x.Name == (string)e.DocumentSource);
            if(diagramInfo != null)
                diagram.LoadDocument(new MemoryStream(diagramInfo.Data));
            e.Handled = true;
        }

        private void OnShowingSaveDialog(object sender, DevExpress.Xpf.Diagram.DiagramShowingSaveDialogEventArgs e) {
            var viewModel = SelectDiagramViewModel.Create();
            viewModel.SelectedName = (string)diagram.DocumentSource;
            var result = saveDialogService.ShowDialog(MessageButton.OKCancel, "Choose a save location", viewModel);
            if(result == MessageResult.OK)
                e.DocumentSourceToSave = viewModel.SelectedName;
            else
                e.Cancel = true;
        }

        private void OnCustomSaveDocument(object sender, DevExpress.Xpf.Diagram.DiagramCustomSaveDocumentEventArgs e) {
            var storage = new DiagramStorage();
            var diagramInfo = storage.DiagramData.FirstOrDefault(x => x.Name == (string)e.DocumentSource);
            if(diagramInfo == null) {
                diagramInfo = new DiagramData() { Name = (string)e.DocumentSource };
                storage.DiagramData.Add(diagramInfo);
            }
            var stream = new MemoryStream();
            diagram.SaveDocument(stream);
            diagramInfo.Data = stream.ToArray();
            storage.SaveChanges();
            e.Handled = true;
        }
    }
    public class SelectDiagramViewModel {
        public static SelectDiagramViewModel Create() {
            return ViewModelSource.Create(() => new SelectDiagramViewModel());
        }
        protected SelectDiagramViewModel() {
            var storage = new DiagramStorage();
            Names = storage.DiagramData.Select(x => x.Name).ToArray();
            SelectedName = Names.FirstOrDefault();
        }
        public string[] Names { get; private set; }
        public virtual string SelectedName { get; set; }
    }
}
csharp
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DXDiagram.CustomDiagramStorage {
    public class DiagramStorage : DbContext {
        public DbSet<DiagramData> DiagramData { get; set; }
    }
    public class DiagramData {
        public int Id { get; set; }
        public string Name { get; set; }
        public byte[] Data { get; set; }
    }
}

See Also

ShowingSaveDialog

CustomLoadDocument

DocumentSource

DiagramControl Class

DiagramControl Members

DevExpress.Xpf.Diagram Namespace