Back to Devexpress

Create a Custom Progress Indicator for the Spreadsheet

wpf-403147-controls-and-libraries-spreadsheet-getting-started-create-a-custom-progress-indicator-for-the-spreadsheet.md

latest12.0 KB
Original Source

Create a Custom Progress Indicator for the Spreadsheet

  • May 19, 2021
  • 5 minutes to read

The WPF Spreadsheet control ships with a predefined progress bar that indicates the progress of lengthy operations (file load/save operations and export to PDF/HTML). To display the progress bar, add a status bar to the Spreadsheet control. See this topic for more information: Create a Simple Spreadsheet Application.

You can use an IProgressIndicationService service to create a custom progress indicator. Create a class that implements this interface and pass a class instance to the SpreadsheetControl.ReplaceService method to replace the default progress indication service with your own service.

Example: Use a Splash Screen as a Custom Progress Indicator

The example below demonstrates how to use a custom splash screen instead of the default progress bar.

View Example: Create a Custom Progress Indicator for the WPF Spreadsheet Control

Create a Custom Splash Screen

Inherit a custom splash screen from the SplashScreenWindow class. Add the following elements to the splash screen:

xaml
<dx:SplashScreenWindow x:Class="WpfSpreadsheetProgressSample.CustomSplashScreen"
        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:dxt="http://schemas.devexpress.com/winfx/2008/xaml/core/themekeys"
        xmlns:mvvm="http://schemas.devexpress.com/winfx/2008/xaml/mvvm"
        BorderBrush="{DynamicResource {dxt:BrushesThemeKey ResourceKey=PanelBorder}}" 
        BorderThickness="1"
        AllowTheming="True"
        Height="120"
        Width="300"
        DataContext="{x:Static mvvm:DXSplashScreenViewModel.DesignTimeData}">
    <dx:BackgroundPanel>
        <StackPanel VerticalAlignment="Center" Margin="16">
            <TextBlock Text="{Binding Title}"
                       FontSize="16"
                       HorizontalAlignment="Left"
                       Margin="0,0,0,8"/>
            <ProgressBar IsIndeterminate="False"
                         Height="20"
                         Width="240"
                         Value="{Binding Progress}"/>
            <TextBlock Text="Cancel"
                       HorizontalAlignment="Right"
                       Margin="0,8,0,0"
                       Foreground="#FF1686F5"
                       TextDecorations="Underline"
                       Cursor="Hand"
                       MouseLeftButtonUp="Cancel_Click" />
        </StackPanel>
    </dx:BackgroundPanel>
</dx:SplashScreenWindow>

A CancellationTokenSource object is passed to the CustomSplashScreen constructor to cancel the operation when a user clicks Cancel.

csharp
using System;
using System.Threading;
using System.Windows.Input;
using DevExpress.Xpf.Core;
// ...

public partial class CustomSplashScreen : SplashScreenWindow {
    readonly CancellationTokenSource cancellationTokenSource;

    public CustomSplashScreen(CancellationTokenSource cancellationTokenSource) {
        this.cancellationTokenSource = cancellationTokenSource;
        InitializeComponent();
    }

    private void Cancel_Click(object sender, MouseButtonEventArgs e) {
        cancellationTokenSource?.Cancel();
    }
}
vb
Imports System
Imports System.Threading
Imports DevExpress.Xpf.Core
' ...

Partial Public Class CustomSplashScreen
    Inherits SplashScreenWindow

    Private ReadOnly cancellationTokenSource As CancellationTokenSource

    Public Sub New(ByVal cancellationTokenSource As CancellationTokenSource)
        Me.cancellationTokenSource = cancellationTokenSource
        InitializeComponent()
    End Sub

    Private Sub Cancel_Click(ByVal sender As Object, ByVal e As MouseButtonEventArgs)
        cancellationTokenSource?.Cancel()
    End Sub
End Class

Implement the Progress Indication Service

Implement the IProgressIndicationService interface methods as shown below and use the SpreadsheetControl.ReplaceService method to substitute the default service with a custom service.

The SplashScreenManager.Create method allows you to create a CustomSplashScreen instance. Pass a DXSplashScreenViewModel object to the method to specify splash screen content.

Use the SpreadsheetControl.UnhandledException event to handle an OperationCanceledException exception that is thrown when a user cancels the operation.

csharp
using System;
using System.Threading;
using DevExpress.Mvvm;
using DevExpress.Office.Services;
using DevExpress.Office.Services.Implementation;
using DevExpress.Services;
using DevExpress.Xpf.Core;
// ...

public partial class MainWindow : ThemedWindow, IProgressIndicationService {
    CancellationTokenSource cancellationTokenSource;
    ICancellationTokenProvider savedCancellationTokenProvider;
    SplashScreenManager splashScreenManager;

    public MainWindow() {
        InitializeComponent();
        // Replace the default progress indication service
        // with a custom service.
        spreadsheetControl1.ReplaceService<IProgressIndicationService>(this);
    }

    void IProgressIndicationService.Begin(string displayName, int minProgress, 
        int maxProgress, int currentProgress) {
        cancellationTokenSource = new CancellationTokenSource();
        // Register a new CancellationTokenProvider instance
        // to process cancellation requests. Save the reference
        // to the previously registered service.
        savedCancellationTokenProvider = spreadsheetControl1.ReplaceService<ICancellationTokenProvider>(
            new CancellationTokenProvider(cancellationTokenSource.Token));
        // Create a CustomSplashScreen instance.
        // Display the name and progress of the running operation 
        // in the splash screen.
        splashScreenManager = SplashScreenManager.Create(() => 
            new CustomSplashScreen(cancellationTokenSource),
            new DXSplashScreenViewModel
            {
                Title = displayName,
                Progress = currentProgress
            });
        // Display the splash screen.
        splashScreenManager.Show();
    }

    void IProgressIndicationService.End() {
        // Close the splash screen.
        splashScreenManager?.Close();
        splashScreenManager = null;
        // Restore previous CancellationTokenProvider.
        spreadsheetControl1.ReplaceService(savedCancellationTokenProvider);
        spreadsheetControl1.UpdateCommandUI();
        // Dispose the CancellationTokenSource object.
        cancellationTokenSource?.Dispose();
        cancellationTokenSource = null;
    }

    void IProgressIndicationService.SetProgress(int currentProgress) {
        // Display the progress of the running operation in the splash screen.
        splashScreenManager.ViewModel.Progress = currentProgress;
    }

    void spreadsheetControl1_UnhandledException(object sender, 
        DevExpress.XtraSpreadsheet.SpreadsheetUnhandledExceptionEventArgs e) {
        // Handle OperationCanceledException.
        if (e.Exception is OperationCanceledException)
            e.Handled = true;
    }
}
vb
Imports System
Imports System.Threading
Imports DevExpress.Mvvm
Imports DevExpress.Office.Services
Imports DevExpress.Office.Services.Implementation
Imports DevExpress.Services
Imports DevExpress.Xpf.Core
' ...

Partial Public Class MainWindow
    Inherits ThemedWindow
    Implements IProgressIndicationService

    Private cancellationTokenSource As CancellationTokenSource
    Private savedCancellationTokenProvider As ICancellationTokenProvider
    Private splashScreenManager As SplashScreenManager

    Public Sub New()
        InitializeComponent()
        ' Replace the default progress indication service
        ' with a custom service.
        spreadsheetControl1.ReplaceService(Of IProgressIndicationService)(Me)
    End Sub

    Private Sub IProgressIndicationService_Begin(ByVal displayName As String,
                                                 ByVal minProgress As Integer,
                                                 ByVal maxProgress As Integer,
                                                 ByVal currentProgress As Integer) _
                                                 Implements IProgressIndicationService.Begin
        cancellationTokenSource = New CancellationTokenSource()
        ' Register a new CancellationTokenProvider instance
        ' to process cancellation requests. Save the reference
        ' to the previously registered service.
        savedCancellationTokenProvider = spreadsheetControl1.ReplaceService(Of ICancellationTokenProvider)(
            New CancellationTokenProvider(cancellationTokenSource.Token))
        ' Create a CustomSplashScreen instance.
        ' Display the name and progress of the running operation 
        ' in the splash screen.
        splashScreenManager = SplashScreenManager.Create(
            Function() New CustomSplashScreen(cancellationTokenSource),
            New DXSplashScreenViewModel With {
            .Title = displayName,
            .Progress = currentProgress
        })
        ' Display the splash screen.
        splashScreenManager.Show()
    End Sub

    Private Sub IProgressIndicationService_End() _
        Implements IProgressIndicationService.End
        ' Close the splash screen.
        splashScreenManager?.Close()
        splashScreenManager = Nothing
        ' Restore previous CancellationTokenProvider.
        spreadsheetControl1.ReplaceService(savedCancellationTokenProvider)
        spreadsheetControl1.UpdateCommandUI()
        ' Dispose the CancellationTokenSource object.
        cancellationTokenSource?.Dispose()
        cancellationTokenSource = Nothing
    End Sub

    Private Sub IProgressIndicationService_SetProgress(ByVal currentProgress As Integer) _ 
        Implements IProgressIndicationService.SetProgress
        ' Display the progress of the running operation in the splash screen.
        splashScreenManager.ViewModel.Progress = currentProgress
    End Sub

    Private Sub spreadsheetControl1_UnhandledException(ByVal sender As Object, 
        ByVal e As DevExpress.XtraSpreadsheet.SpreadsheetUnhandledExceptionEventArgs)
        ' Handle OperationCanceledException.
        If TypeOf e.Exception Is OperationCanceledException Then
            e.Handled = True
        End If
    End Sub
End Class