Back to Devexpress

MVVM - Use Report Designer API from ViewModel

xtrareports-403465-desktop-reporting-wpf-reporting-end-user-report-designer-for-wpf-api-and-customization-mvvm-use-report-designer-api-from-view-model.md

latest11.9 KB
Original Source

MVVM - Use Report Designer API from ViewModel

  • Apr 26, 2024
  • 5 minutes to read

The DevExpress MVVM Framework allows you to access the ReportDesigner methods from commands defined in the ViewModel. You can develop your own API that extends the built-in functionality of ReportDesigner and optimally meets your requirements.

In this example the Behavior mechanism initializes a service that implements ReportDesigner actions. The service is defined as follows:

csharp
using DevExpress.Mvvm.UI;
using DevExpress.Mvvm.UI.Interactivity;
using DevExpress.Xpf.Reports.UserDesigner;
using DevExpress.XtraReports.UI;
using System;
using System.Collections.Generic;
using System.IO;

namespace ManipulateReportDesignerDocuments_MVVM {
    public interface IReportDesignerAPIService {
        IEnumerable<ReportDesignerDocument> Documents { get; }
        ReportDesignerDocument ActiveDocument { get; }
        ReportDesignerDocument NewReport(XtraReport report = null);
        ReportDesignerDocument Open();
        ReportDesignerDocument Open(Stream stream);
    }

    public class ReportDesignerAPIService : ServiceBase, IReportDesignerAPIService {
        ReportDesigner Designer => (ReportDesigner)AssociatedObject;

        public IEnumerable<ReportDesignerDocument> Documents => Designer.Documents;

        public ReportDesignerDocument ActiveDocument => Designer.ActiveDocument;

        public ReportDesignerDocument NewReport(XtraReport report = null) {
            Func<XtraReport> reportFactory = null;
            if(report != null)
                reportFactory = () => report;
            return Designer.NewDocument(reportFactory);
        }

        public ReportDesignerDocument Open() {
            return Designer.OpenDocument();
        }

        public ReportDesignerDocument Open(Stream stream) {
            return Designer.OpenDocument(stream);
        }
    }
}
vb
Imports DevExpress.Mvvm.UI
Imports DevExpress.Mvvm.UI.Interactivity
Imports DevExpress.Xpf.Reports.UserDesigner
Imports DevExpress.XtraReports.UI
Imports System
Imports System.Collections.Generic
Imports System.IO

Namespace ManipulateReportDesignerDocuments_MVVM
    Public Interface IReportDesignerAPIService
        ReadOnly Property Documents() As IEnumerable(Of ReportDesignerDocument)
        ReadOnly Property ActiveDocument() As ReportDesignerDocument
        Function NewReport(Optional ByVal report As XtraReport = Nothing) As ReportDesignerDocument
        Function Open() As ReportDesignerDocument
        Function Open(ByVal stream As Stream) As ReportDesignerDocument
    End Interface

    Public Class ReportDesignerAPIService
        Inherits ServiceBase
        Implements IReportDesignerAPIService

        Private ReadOnly Property Designer() As ReportDesigner
            Get
                Return CType(AssociatedObject, ReportDesigner)
            End Get
        End Property

        Public ReadOnly Property Documents() As IEnumerable(Of ReportDesignerDocument) Implements IReportDesignerAPIService.Documents
            Get
                Return Designer.Documents
            End Get
        End Property

        Public ReadOnly Property ActiveDocument() As ReportDesignerDocument Implements IReportDesignerAPIService.ActiveDocument
            Get
                Return Designer.ActiveDocument
            End Get
        End Property

        Public Function NewReport(Optional ByVal report As XtraReport = Nothing) As ReportDesignerDocument Implements IReportDesignerAPIService.NewReport
            Dim reportFactory As Func(Of XtraReport) = Nothing
            If report IsNot Nothing Then
                reportFactory = Function() report
            End If
            Return Designer.NewDocument(reportFactory)
        End Function

        Public Function Open() As ReportDesignerDocument Implements IReportDesignerAPIService.Open
            Return Designer.OpenDocument()
        End Function

        Public Function Open(ByVal stream As Stream) As ReportDesignerDocument Implements IReportDesignerAPIService.Open
            Return Designer.OpenDocument(stream)
        End Function
    End Class
End Namespace

The ReportDesignerAPIService is specified as custom behavior. For more information on the Behavior mechanism in DevExpress MVVM Framework, review the following help topic: Behaviors.

The following code uses the ReportDesignerAPIService class as a custom Behavior for the ReportDesigner element in the View:

xaml
<dx:ThemedWindow x:Class="ManipulateReportDesignerDocuments_MVVM.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:ManipulateReportDesignerDocuments_MVVM"
        xmlns:dxrud="http://schemas.devexpress.com/winfx/2008/xaml/reports/userdesigner" 
        xmlns:dxmvvm="http://schemas.devexpress.com/winfx/2008/xaml/mvvm"
        xmlns:dx="http://schemas.devexpress.com/winfx/2008/xaml/core"
        mc:Ignorable="d" WindowKind="Tabbed" WindowState="Maximized"
        Title="MainWindow" Height="450" Width="800">
        <!-- ... -->
        <dxrud:ReportDesigner>
            <dxrud:ReportDesignerBrowserView CloseWindowWhenLastTabIsClosed="False" />
            <dxrud:ReportDesigner.DocumentSource>
                <Binding Path="DefaultReport" />
            </dxrud:ReportDesigner.DocumentSource>
            <dxmvvm:Interaction.Behaviors>
                <local:ReportDesignerAPIService />
            </dxmvvm:Interaction.Behaviors>
        </dxrud:ReportDesigner>
        <!-- ... -->
</dx:ThemedWindow>

The MainViewModel ViewModel class gets the ReportDesignerAPIService service and implements MVVM commands based on the service methods:

csharp
using DevExpress.Mvvm;
using DevExpress.Mvvm.DataAnnotations;
using DevExpress.Xpf.Reports.UserDesigner;
using DevExpress.XtraReports.UI;
using System;
using System.Linq;
using System.Windows;
using System.Windows.Resources;

namespace ManipulateReportDesignerDocuments_MVVM {
    public class MainViewModel : ViewModelBase {
        public XtraReport DefaultReport { get; set; }

        IReportDesignerAPIService ReportDesignerAPI => ServiceContainer.GetService<IReportDesignerAPIService>();

        protected override void OnInitializeInRuntime() {
            base.OnInitializeInRuntime();
            DefaultReport = new XtraReport();
        }

        [Command]
        public void NewReport() {
            ReportDesignerAPI.NewReport();
        }
        public bool CanNewReport() => ReportDesignerAPI != null;

        [Command]
        public void OpenReport() {
            ReportDesignerAPI.Open();
        }
        public bool CanOpenReport() => ReportDesignerAPI != null;

        [Command]
        public void OpenReportFromStream() {
            var stream = Application.GetResourceStream(new Uri("Resources/Invoice.repx", UriKind.Relative))?.Stream;
            if(stream != null) {
                using(stream) {
                    ReportDesignerAPI.Open(stream);
                }
            }
        }
        public bool CanOpenReportFromStream() => ReportDesignerAPI != null;

        [Command]
        public void CloseActiveDocument() {
            ReportDesignerAPI.ActiveDocument.Close(true);
        }
        public bool CanCloseActiveDocument() => ReportDesignerAPI?.ActiveDocument != null;

        [Command]
        public void ActivateFirstDocumentTab() {
            ReportDesignerDocument firstTab = ReportDesignerAPI.Documents.First();
            firstTab.Activate();
        }
        public bool CanActivateFirstDocumentTab() => ReportDesignerAPI?.Documents.Any() ?? false;

        [Command]
        public void SwitchActiveDocumentView() {
            ReportDesignerDocument activeDocument = ReportDesignerAPI.ActiveDocument;
            activeDocument.ViewKind = activeDocument.ViewKind == ReportDesignerDocumentViewKind.Designer
                ? ReportDesignerDocumentViewKind.Preview
                : ReportDesignerDocumentViewKind.Designer;
        }
        public bool CanSwitchActiveDocumentView() => ReportDesignerAPI?.ActiveDocument != null;
    }
}
vb
Imports DevExpress.Mvvm
Imports DevExpress.Mvvm.DataAnnotations
Imports DevExpress.Xpf.Reports.UserDesigner
Imports DevExpress.XtraReports.UI
Imports System
Imports System.Linq
Imports System.Windows
Imports System.Windows.Resources

Namespace ManipulateReportDesignerDocuments_MVVM
    Public Class MainViewModel
        Inherits ViewModelBase

        Public Property DefaultReport() As XtraReport

        Private ReadOnly Property ReportDesignerAPI() As IReportDesignerAPIService
            Get
                Return ServiceContainer.GetService(Of IReportDesignerAPIService)()
            End Get
        End Property

        Protected Overrides Sub OnInitializeInRuntime()
            MyBase.OnInitializeInRuntime()
            DefaultReport = New XtraReport()
        End Sub

        <Command>
        Public Sub NewReport()
            ReportDesignerAPI.NewReport()
        End Sub
        Public Function CanNewReport() As Boolean
            Return ReportDesignerAPI IsNot Nothing
        End Function

        <Command>
        Public Sub OpenReport()
            ReportDesignerAPI.Open()
        End Sub
        Public Function CanOpenReport() As Boolean
            Return ReportDesignerAPI IsNot Nothing
        End Function

        <Command>
        Public Sub OpenReportFromStream()
            Dim stream = Application.GetResourceStream(New Uri("Resources/Invoice.repx", UriKind.Relative))?.Stream
            If stream IsNot Nothing Then
                Using stream
                    ReportDesignerAPI.Open(stream)
                End Using
            End If
        End Sub
        Public Function CanOpenReportFromStream() As Boolean
            Return ReportDesignerAPI IsNot Nothing
        End Function

        <Command>
        Public Sub CloseActiveDocument()
            ReportDesignerAPI.ActiveDocument.Close(True)
        End Sub
        Public Function CanCloseActiveDocument() As Boolean
            Return ReportDesignerAPI?.ActiveDocument IsNot Nothing
        End Function

        <Command>
        Public Sub ActivateFirstDocumentTab()
            Dim firstTab As ReportDesignerDocument = ReportDesignerAPI.Documents.First()
            firstTab.Activate()
        End Sub
        Public Function CanActivateFirstDocumentTab() As Boolean
            Return If(ReportDesignerAPI?.Documents.Any(), False)
        End Function

        <Command>
        Public Sub SwitchActiveDocumentView()
            Dim activeDocument As ReportDesignerDocument = ReportDesignerAPI.ActiveDocument
            activeDocument.ViewKind = If(activeDocument.ViewKind = ReportDesignerDocumentViewKind.Designer, ReportDesignerDocumentViewKind.Preview, ReportDesignerDocumentViewKind.Designer)
        End Sub
        Public Function CanSwitchActiveDocumentView() As Boolean
            Return ReportDesignerAPI?.ActiveDocument IsNot Nothing
        End Function
    End Class
End Namespace

For more information on auto-generated commands, review the following help topic: POCO Commands.

The application appears as follows:

View Example: How to Use MVVM Framework to Create Custom Commands for Report Designer