Back to Devexpress

How to: Handle DiagramControl Events to Save Diagrams to a Database instead of a File System

windowsforms-118075-controls-and-libraries-diagrams-examples-how-to-handle-diagramcontrol-events-to-save-diagrams-to-a-database-instead-of-a-file-system.md

latest22.2 KB
Original Source

How to: Handle DiagramControl Events to Save Diagrams to a Database instead of a File System

  • Nov 13, 2018
  • 10 minutes to read

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 method (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 - This 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 in the event args 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.

View Example

csharp
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Linq;
using System.Windows.Forms;
using DevExpress.XtraEditors;

namespace XtraDiagram.CustomDiagramStorage {
    public partial class DiagramOpenDialog : DevExpress.XtraEditors.XtraForm {
        public string SelectedItem { get; set; }

        public DiagramOpenDialog() {
            InitializeComponent();
        }

        protected override void OnLoad(EventArgs e) {
            base.OnLoad(e);
            PopulateListBox();
        }

        private void PopulateListBox() {
            if (!DesignMode)
                listBoxControl1.DataSource = DiagramRepository.GetDiagramNames();
        }

        private void listBoxControl1_MouseDoubleClick(object sender, MouseEventArgs e) {
            var itemIndex = listBoxControl1.IndexFromPoint(e.Location);
            if (itemIndex > -1) {
                DialogResult = DialogResult.OK;
                Close();
            }
        }

        private void listBoxControl1_SelectedIndexChanged(object sender, EventArgs e) {
            OnSelectedItemChanged();
        }

        protected virtual void OnSelectedItemChanged() {
            SelectedItem = listBoxControl1.SelectedItem as string;
        }
    }
}
csharp
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace XtraDiagram.CustomDiagramStorage {
    public class DiagramSelector {
        public static string SelectDiagramToOpen() {
            var selector = new DiagramOpenDialog() { Text = "Choose a diagram to open" };
            return ShowDialogCore(selector);
        }

        public static string SelectDiagramToSave() {
            var selector = new DiagramSaveDialog() { Text = "Choose a save location" };
            return ShowDialogCore(selector);
        }

        protected static string ShowDialogCore(DiagramOpenDialog dialog) {
            dialog.ShowDialog();
            return dialog.DialogResult == DialogResult.OK ? dialog.SelectedItem : null;
        }
    }
}
csharp
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Linq;
using System.Windows.Forms;
using DevExpress.XtraEditors;

namespace XtraDiagram.CustomDiagramStorage {
    public partial class DiagramSaveDialog : DiagramOpenDialog {
        public DiagramSaveDialog() {
            InitializeComponent();
        }

        protected override void OnSelectedItemChanged() {
            base.OnSelectedItemChanged();
            textEdit1.Text = SelectedItem;
        }

        protected override void OnClosing(CancelEventArgs e) {
            base.OnClosing(e);
            SelectedItem = textEdit1.Text;
        }
    }
}
csharp
using DevExpress.Diagram.Core;
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;
using DevExpress.XtraDiagram;

namespace XtraDiagram.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 DevExpress.Utils.PointFloat(200, 100 + i * 100),
                    Width = 100,
                    Height = 50,
                    Content = "Item " + (i + 1).ToString(),
                });
                if(i == 0)
                    continue;
                diagram.SelectedStencils = new StencilCollection(new string[] {
                DiagramToolboxRegistrator.Stencils.ElementAt(i).Id
                });
                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.Data.Entity;
using System.Linq;
using System.Windows.Forms;
using DevExpress.Internal;

namespace XtraDiagram.CustomDiagramStorage {
    static class Program {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main() {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            DbEngineDetector.PatchConnectionStringsAndConfigureEntityFrameworkDefaultConnectionFactory();
            Database.SetInitializer(new DiagramStorageInitializer());

            Application.Run(new Form1());
        }
    }
}
csharp
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Windows.Threading;
using DevExpress.Diagram.Core;
using DevExpress.XtraDiagram;

namespace XtraDiagram.CustomDiagramStorage {
    public partial class Form1 : DevExpress.XtraBars.Ribbon.RibbonForm {
        public Form1() {
            InitializeComponent();
        }
        protected override void OnLoad(EventArgs e) {
            base.OnLoad(e);
            diagramControl1.InitializeRibbon(ribbonControl1);
            diagramControl1.OpenFile();
        }
        void OnShowingOpenDialog(object sender, DiagramShowingOpenDialogEventArgs e) {
            var diagramName = DiagramSelector.SelectDiagramToOpen();
            if(diagramName != null)
                e.DocumentSourceToOpen = diagramName;
            else
                e.Cancel = true;
        }
        void OnCustomLoadDocument(object sender, DiagramCustomLoadDocumentEventArgs e) {
            if(e.DocumentSource == null) {
                diagramControl1.NewDocument();
                Text = "(New Document)";
                return;
            }
            var diagramName = (string)e.DocumentSource;
            Text = diagramName;
            var diagramData = DiagramRepository.GetDiagramData(diagramName);
            if (diagramData != null)
                diagramControl1.LoadDocument(new MemoryStream(diagramData));
            e.Handled = true;
        }
        void OnShowingSaveDialog(object sender, DiagramShowingSaveDialogEventArgs e) {
            var diagramName = DiagramSelector.SelectDiagramToSave();
            if(diagramName != null)
                e.DocumentSourceToSave = diagramName;
            else
                e.Cancel = true;
        }
        void OnCustomSaveDocument(object sender, DiagramCustomSaveDocumentEventArgs e) {
            var diagramName = (string)e.DocumentSource;
            Text = diagramName;
            var stream = new MemoryStream();
            diagramControl1.SaveDocument(stream);
            var diagramData = stream.ToArray();
            DiagramRepository.SaveDiagramData(diagramName, diagramData);
            e.Handled = true;
        }
    }
}
csharp
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace XtraDiagram.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; }
    }
    public class DiagramRepository {
        public static IEnumerable<string> GetDiagramNames() {
            var storage = new DiagramStorage();
            return storage.DiagramData.Select(x => x.Name).ToList();
        }

        public static byte[] GetDiagramData(string diagramName) {
            var storage = new DiagramStorage();
            return storage.DiagramData.FirstOrDefault(x => x.Name == diagramName).Data;
        }
        public static void SaveDiagramData(string diagramName, byte[] diagramData) {
            var storage = new DiagramStorage();
            var diagramInfo = storage.DiagramData.FirstOrDefault(x => x.Name == diagramName);
            if (diagramInfo == null) {
                diagramInfo = new DiagramData() { Name = diagramName };
                storage.DiagramData.Add(diagramInfo);
            }
            diagramInfo.Data = diagramData;
            storage.SaveChanges();
        }
    }
}
vb
Imports System
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Data
Imports System.Drawing
Imports System.Text
Imports System.Linq
Imports System.Windows.Forms
Imports DevExpress.XtraEditors

Namespace XtraDiagram.CustomDiagramStorage
    Partial Public Class DiagramSaveDialog
        Inherits DiagramOpenDialog

        Public Sub New()
            InitializeComponent()
        End Sub

        Protected Overrides Sub OnSelectedItemChanged()
            MyBase.OnSelectedItemChanged()
            textEdit1.Text = SelectedItem
        End Sub

        Protected Overrides Sub OnClosing(ByVal e As CancelEventArgs)
            MyBase.OnClosing(e)
            SelectedItem = textEdit1.Text
        End Sub
    End Class
End Namespace
vb
Imports System
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Data
Imports System.Drawing
Imports System.Text
Imports System.Linq
Imports System.Windows.Forms
Imports DevExpress.XtraEditors

Namespace XtraDiagram.CustomDiagramStorage
    Partial Public Class DiagramOpenDialog
        Inherits DevExpress.XtraEditors.XtraForm

        Public Property SelectedItem() As String

        Public Sub New()
            InitializeComponent()
        End Sub

        Protected Overrides Sub OnLoad(ByVal e As EventArgs)
            MyBase.OnLoad(e)
            PopulateListBox()
        End Sub

        Private Sub PopulateListBox()
            If Not DesignMode Then
                listBoxControl1.DataSource = DiagramRepository.GetDiagramNames()
            End If
        End Sub

        Private Sub listBoxControl1_MouseDoubleClick(ByVal sender As Object, ByVal e As MouseEventArgs) Handles listBoxControl1.MouseDoubleClick
            Dim itemIndex = listBoxControl1.IndexFromPoint(e.Location)
            If itemIndex > -1 Then
                DialogResult = DialogResult.OK
                Close()
            End If
        End Sub

        Private Sub listBoxControl1_SelectedIndexChanged(ByVal sender As Object, ByVal e As EventArgs) Handles listBoxControl1.SelectedIndexChanged
            OnSelectedItemChanged()
        End Sub

        Protected Overridable Sub OnSelectedItemChanged()
            SelectedItem = TryCast(listBoxControl1.SelectedItem, String)
        End Sub
    End Class
End Namespace
vb
Imports System
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Data
Imports System.Drawing
Imports System.IO
Imports System.Linq
Imports System.Text
Imports System.Windows.Forms
Imports System.Windows.Threading
Imports DevExpress.Diagram.Core
Imports DevExpress.XtraDiagram

Namespace XtraDiagram.CustomDiagramStorage
    Partial Public Class Form1
        Inherits DevExpress.XtraBars.Ribbon.RibbonForm

        Public Sub New()
            InitializeComponent()
        End Sub
        Protected Overrides Sub OnLoad(ByVal e As EventArgs)
            MyBase.OnLoad(e)
            diagramControl1.InitializeRibbon(ribbonControl1)
            diagramControl1.OpenFile()
        End Sub
        Private Sub OnShowingOpenDialog(ByVal sender As Object, ByVal e As DiagramShowingOpenDialogEventArgs) Handles diagramControl1.ShowingOpenDialog
            Dim diagramName = DiagramSelector.SelectDiagramToOpen()
            If diagramName IsNot Nothing Then
                e.DocumentSourceToOpen = diagramName
            Else
                e.Cancel = True
            End If
        End Sub
        Private Sub OnCustomLoadDocument(ByVal sender As Object, ByVal e As DiagramCustomLoadDocumentEventArgs) Handles diagramControl1.CustomLoadDocument
            If e.DocumentSource Is Nothing Then
                diagramControl1.NewDocument()
                Text = "(New Document)"
                Return
            End If
            Dim diagramName = CStr(e.DocumentSource)
            Text = diagramName
            Dim diagramData = DiagramRepository.GetDiagramData(diagramName)
            If diagramData IsNot Nothing Then
                diagramControl1.LoadDocument(New MemoryStream(diagramData))
            End If
            e.Handled = True
        End Sub
        Private Sub OnShowingSaveDialog(ByVal sender As Object, ByVal e As DiagramShowingSaveDialogEventArgs) Handles diagramControl1.ShowingSaveDialog
            Dim diagramName = DiagramSelector.SelectDiagramToSave()
            If diagramName IsNot Nothing Then
                e.DocumentSourceToSave = diagramName
            Else
                e.Cancel = True
            End If
        End Sub
        Private Sub OnCustomSaveDocument(ByVal sender As Object, ByVal e As DiagramCustomSaveDocumentEventArgs) Handles diagramControl1.CustomSaveDocument
            Dim diagramName = CStr(e.DocumentSource)
            Text = diagramName
            Dim stream = New MemoryStream()
            diagramControl1.SaveDocument(stream)
            Dim diagramData = stream.ToArray()
            DiagramRepository.SaveDiagramData(diagramName, diagramData)
            e.Handled = True
        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 XtraDiagram.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
    Public Class DiagramRepository
        Public Shared Function GetDiagramNames() As IEnumerable(Of String)
            Dim storage = New DiagramStorage()
            Return storage.DiagramData.Select(Function(x) x.Name).ToList()
        End Function

        Public Shared Function GetDiagramData(ByVal diagramName As String) As Byte()
            Dim storage = New DiagramStorage()
            Return storage.DiagramData.FirstOrDefault(Function(x) x.Name = diagramName).Data
        End Function
        Public Shared Sub SaveDiagramData(ByVal diagramName As String, ByVal diagramData() As Byte)
            Dim storage = New DiagramStorage()
            Dim diagramInfo = storage.DiagramData.FirstOrDefault(Function(x) x.Name = diagramName)
            If diagramInfo Is Nothing Then
                diagramInfo = New DiagramData() With {.Name = diagramName}
                storage.DiagramData.Add(diagramInfo)
            End If
            diagramInfo.Data = diagramData
            storage.SaveChanges()
        End Sub
    End Class
End Namespace
vb
Imports DevExpress.Diagram.Core
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
Imports DevExpress.XtraDiagram

Namespace XtraDiagram.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 DevExpress.Utils.PointFloat(200, 100 + i * 100), .Width = 100, .Height = 50, .Content = "Item " & (i + 1).ToString()})
                If i = 0 Then
                    Continue For
                End If
                diagram.SelectedStencils = New StencilCollection(New String() { DiagramToolboxRegistrator.Stencils.ElementAt(i).Id })
                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.Linq
Imports System.Text
Imports System.Windows.Forms

Namespace XtraDiagram.CustomDiagramStorage
    Public Class DiagramSelector
        Public Shared Function SelectDiagramToOpen() As String
            Dim selector = New DiagramOpenDialog() With {.Text = "Choose a diagram to open"}
            Return ShowDialogCore(selector)
        End Function

        Public Shared Function SelectDiagramToSave() As String
            Dim selector = New DiagramSaveDialog() With {.Text = "Choose a save location"}
            Return ShowDialogCore(selector)
        End Function

        Protected Shared Function ShowDialogCore(ByVal dialog As DiagramOpenDialog) As String
            dialog.ShowDialog()
            Return If(dialog.DialogResult = DialogResult.OK, dialog.SelectedItem, Nothing)
        End Function
    End Class
End Namespace
vb
Imports System
Imports System.Collections.Generic
Imports System.Data.Entity
Imports System.Linq
Imports System.Windows.Forms
Imports DevExpress.Internal

Namespace XtraDiagram.CustomDiagramStorage
    Friend NotInheritable Class Program

        Private Sub New()
        End Sub

        ''' <summary>
        ''' The main entry point for the application.
        ''' </summary>
        <STAThread> _
        Shared Sub Main()
            Application.EnableVisualStyles()
            Application.SetCompatibleTextRenderingDefault(False)

            DbEngineDetector.PatchConnectionStringsAndConfigureEntityFrameworkDefaultConnectionFactory()
            Database.SetInitializer(New DiagramStorageInitializer())

            Application.Run(New Form1())
        End Sub
    End Class
End Namespace