Back to Devexpress

MVVM - Bind to a Report in a ViewModel

xtrareports-403457-desktop-reporting-wpf-reporting-wpf-reporting-document-preview-api-and-customization-mvvm-bind-to-report-in-view-model.md

latest8.7 KB
Original Source

MVVM - Bind to a Report in a ViewModel

  • Apr 26, 2024
  • 4 minutes to read

The DevExpress MVVM Framework allows you to bind the DocumentPreviewControl to a report in a view model. The view model contains the code required to retrieve a report from the storage.

The following code defines the binding in XAML:

xaml
<dx:ThemedWindow x:Class="ShowReportPreview_MVVM.MainWindow"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:models="clr-namespace:ShowReportPreview_MVVM.Models"
                 xmlns:dxe="http://schemas.devexpress.com/winfx/2008/xaml/editors"
                 xmlns:dxp="http://schemas.devexpress.com/winfx/2008/xaml/printing"
                 xmlns:dx="http://schemas.devexpress.com/winfx/2008/xaml/core"
                 xmlns:dxmvvm="http://schemas.devexpress.com/winfx/2008/xaml/mvvm" 
                 Title="MainWindow" WindowState="Maximized"
                 DataContext="{dxmvvm:ViewModelSource Type=models:ReportCatalogViewModel}">
<!-- ... -->
<dxp:DocumentPreviewControl Name="preview"
                            RequestDocumentCreation="True"
                            DocumentSource="{Binding Report}" />

Thw DocumentPreviewControl.DocumentSource property is bound to the ReportCatalogViewModel.Report property.

The ReportCatalogViewModel is the ViewModel class implemented as follows:

csharp
using DevExpress.Mvvm;
using DevExpress.Mvvm.DataAnnotations;
using DevExpress.XtraReports.UI;
// ...
    [POCOViewModel]
    public class ReportCatalogViewModel : ViewModelBase {
    // ...
        public virtual XtraReport Report { get; protected set; }
        // ...
    }
vb
Imports DevExpress.Mvvm
Imports DevExpress.Mvvm.DataAnnotations
Imports DevExpress.XtraReports.UI
' ...
    <POCOViewModel>
    Public Class ReportCatalogViewModel
        Inherits ViewModelBase
' ...
        Public Overridable Property Report() As XtraReport
' ...
    End Class

For more information on POCO View Models, review the following help topic: Runtime-generated POCO View Models.

The ViewModel retrieves reports from a database storage and creates a collection of ReportCatalogItem objects. The ReportCatalogItem class is defined as follows:

csharp
using System.ComponentModel.DataAnnotations;
using System.Data.Entity;
// ...
    public class ReportCatalogItem {
        [Key]
        public string ID { get; set; }
        public string ReportName { get; set; }
        public byte[] Layout { get; set; }
    }
vb
Imports System.ComponentModel.DataAnnotations
Imports System.Data.Entity
' ...
    Public Class ReportCatalogItem
        <Key>
        Public Property ID() As String
        Public Property ReportName() As String
        Public Property Layout() As Byte()
    End Class

Use the bindable AvailableReports property to access the ReportCatalogItem collection, as shown in the following code sample:

csharp
using DevExpress.Mvvm;
using DevExpress.Mvvm.DataAnnotations;
using DevExpress.XtraReports.UI;
using ShowReportPreview_MVVM.Data;
using System.Collections.Generic;
using System.Data.Entity;
using System.IO;
using System.Linq;
// ...
    [POCOViewModel]
    public class ReportCatalogViewModel : ViewModelBase {
        readonly ReportCatalogDbContext dbContext = new ReportCatalogDbContext();

        public virtual IEnumerable<ReportCatalogItem> AvailableReports { get; protected set; }

        public virtual XtraReport Report { get; protected set; }

        protected override void OnInitializeInRuntime() {
            base.OnInitializeInRuntime();
            dbContext.ReportItems.Load();
            AvailableReports = dbContext.ReportItems.Local;
        }
        // ...
    }
vb
Imports DevExpress.Mvvm
Imports DevExpress.Mvvm.DataAnnotations
Imports DevExpress.XtraReports.UI
' ...
    <POCOViewModel>
    Public Class ReportCatalogViewModel
        Inherits ViewModelBase

        Private dbContext As New ReportCatalogDbContext()

        Private privateAvailableReports As IEnumerable(Of ReportCatalogItem)
        Public Overridable Property AvailableReports() As IEnumerable(Of ReportCatalogItem)
            Get
                Return privateAvailableReports
            End Get
            Protected Set(ByVal value As IEnumerable(Of ReportCatalogItem))
                privateAvailableReports = value
            End Set
        End Property

        Public Overridable Property Report() As XtraReport

        Protected Overrides Sub OnInitializeInRuntime()
            MyBase.OnInitializeInRuntime()
            dbContext = New ReportCatalogDbContext()
            dbContext.ReportItems.Load()
            AvailableReports = dbContext.ReportItems.Local
        End Sub
' ...
    End Class

The DevExpress MVVM Framework enables you to create commands that can be bound to any element in the View. Review the following help topic for more information: POCO Commands.

The following code implements the ShowPreview command that opens a report with the DocumentPreviewControl located in the View, and the ShowPreviewInNewWindow command that uses the DevExpress.Mvvm.IDialogService to open a report in a modal window:

csharp
using DevExpress.Mvvm;
using DevExpress.Mvvm.DataAnnotations;
using DevExpress.XtraReports.UI;
using ShowReportPreview_MVVM.Data;
using System.Collections.Generic;
using System.Data.Entity;
using System.IO;
using System.Linq;
// ...
    [POCOViewModel]
    public class ReportCatalogViewModel : ViewModelBase {
    // ...
        public virtual IEnumerable<ReportCatalogItem> AvailableReports { get; protected set; }
        // ...
        public void ShowPreview(string reportId) {
            Report = LoadReport(reportId);
        }
        protected bool CanShowPreview(string reportId) => AvailableReports.Any(x => x.ID == reportId);

        public void ShowPreviewInNewWindow(string reportId) {
            XtraReport report = LoadReport(reportId);
            DocumentPreviewDialogViewModel dialogModel = new DocumentPreviewDialogViewModel(report);
            IDialogService previewDialogService = GetService<IDialogService>("previewDialogService");
            previewDialogService.ShowDialog(null, "Document Preview", dialogModel);
        }
        protected bool CanShowPreviewInNewWindow(string reportId) => CanShowPreview(reportId);

        XtraReport LoadReport(string reportId) {
            ReportCatalogItem reportItem = AvailableReports.Single(x => x.ID == reportId);
            using(var stream = new MemoryStream(reportItem.Layout)) {
                return XtraReport.FromStream(stream);
            }
        }
    }
vb
Imports DevExpress.Mvvm
Imports DevExpress.Mvvm.DataAnnotations
Imports DevExpress.XtraReports.UI
' ...
    <POCOViewModel>
    Public Class ReportCatalogViewModel
        Inherits ViewModelBase

        Private dbContext As New ReportCatalogDbContext()

        Private privateAvailableReports As IEnumerable(Of ReportCatalogItem)
        Public Overridable Property AvailableReports() As IEnumerable(Of ReportCatalogItem)
            Get
                Return privateAvailableReports
            End Get
            Protected Set(ByVal value As IEnumerable(Of ReportCatalogItem))
                privateAvailableReports = value
            End Set
        End Property

        Public Overridable Property Report() As XtraReport

        Protected Overrides Sub OnInitializeInRuntime()
            MyBase.OnInitializeInRuntime()
            dbContext = New ReportCatalogDbContext()
            dbContext.ReportItems.Load()
            AvailableReports = dbContext.ReportItems.Local
        End Sub
' ...
    End Class

The application appears as follows:

View Example: How to Use the DocumentPreviewControl in WPF MVVM Application to Preview a Report