xtrareports-403465-desktop-reporting-wpf-reporting-end-user-report-designer-for-wpf-api-and-customization-mvvm-use-report-designer-api-from-view-model.md
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:
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);
}
}
}
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:
<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:
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;
}
}
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