Create a Custom Progress Indicator for the Spreadsheet
- 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.
Create a Custom Splash Screen
Inherit a custom splash screen from the SplashScreenWindow class. Add the following elements to the splash screen:
- TextBox — displays the name of the operation.
- ProgressBar — indicates the progress of the operation.
- TextBox — displays the Cancel hyperlink that allows users to cancel the operation.
<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.
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();
}
}
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.
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;
}
}