Added `ZoomLevelChanged` to available events in `DEVEXPRESS_V25_LIMITATIONS.md` and clarified missing events. Created a detailed migration plan in `MIGRATION_PLAN.md` for transitioning from PDF.js to DevExpress DxPdfViewer v25.2.3, including a hybrid approach, testing checklist, and rollback plan. Summarized research findings and API verification in `SESSION_SUMMARY.md`, highlighting limitations, risks, and recommendations for the migration.
7.2 KiB
7.2 KiB
DevExpress Blazor PdfViewer v25.2.3 - Verified API Reference
Source: All information in this document has been verified from the actual source code of
DevExpress.Blazor.PdfViewerv25.2.3 package. AI-generated API suggestions (GoToPageAsync, PageNumberChanged, etc.) are NOT real – do not use them.
Verified Available Parameters
| Property | Type | Access | Default | Description |
|---|---|---|---|---|
DocumentContent |
byte[] |
[Parameter] GET/SET |
– | Feeds PDF content as byte array |
CssClass |
string |
[Parameter] GET/SET |
– | Assigns CSS class to component |
DocumentName |
string |
[Parameter] GET/SET |
"Document" |
Download filename |
IsSinglePagePreview |
bool |
[Parameter] GET/SET |
false |
Single page mode |
SizeMode |
SizeMode? |
[Parameter] GET/SET |
null |
Small, Medium, Large |
ZoomLevel |
double |
[Parameter] GET/SET |
-1 |
Factor (not percentage). 1.5 = 150% |
ActivePageIndex |
int |
GET only | – | Active page index (0-based). No SET. |
PageCount |
int |
GET only | – | Total page count in document |
Available Events
CustomizeToolbar– Allows toolbar customizationZoomLevelChanged– Fires when ZoomLevel property changes (EventCallback)
Missing Events (NOT AVAILABLE in v25.2.3)
PageNumberChanged/ActivePageIndexChanged– Not available- User scrolling or native toolbar page changes do not trigger C# code
Missing Properties (NOT AVAILABLE in v25.2.3)
ToolbarVisible– Not available (toolbar cannot be completely hidden)ActivePageIndex(settable) – Read-only; no programmatic page navigation
Missing Methods (NOT AVAILABLE in v25.2.3)
GoToPageAsync()– Not availableGoToNextPageAsync()– Not availableZoomAsync()– Not available
Critical Integration Notes
ZoomLevel takes factor, not percentage
// CORRECT
_viewerZoomLevel = 1.5; // viewer displays "150%"
_viewerZoomLevel = _currentZoom / 100d; // _currentZoom=150 -> 1.5
// WRONG
_viewerZoomLevel = 150; // viewer displays "15000%"
PageCount replaces JS call
// CORRECT - read directly from component (no JS needed)
_totalPages = _pdfViewer.PageCount;
// OLD method (no longer needed for this purpose)
// _totalPages = await JSRuntime.InvokeAsync<int>("pdfViewer.getTotalPages");
ActivePageIndex is read-only
// CORRECT - read for state synchronization
var currentPage = _pdfViewer.ActivePageIndex + 1; // convert to 1-based
// COMPILE ERROR - no setter
// _pdfViewer.ActivePageIndex = 3; // COMPILE ERROR
DocumentContent byte[] feeding
<DxPdfViewer @ref="_pdfViewer"
DocumentContent="@_pdfDocumentContent"
ZoomLevel="@_viewerZoomLevel"
IsSinglePagePreview="true" />
@code {
DxPdfViewer? _pdfViewer;
byte[]? _pdfDocumentContent; // populate in OnInitializedAsync
double _viewerZoomLevel = 1.5; // 150%
}
Impact on EnvelopeReceiverPage
Features That Don't Work
- Event-driven overlay updates – No page/zoom change events
- Thumbnail click navigation – Cannot navigate viewer to specific page via C# API
- Cross-page signature navigation – No programmatic page change API
- Automatic overlay synchronization – User scroll/native toolbar doesn't trigger C#
Features That Work
- ZoomLevel binding – Custom zoom buttons can update viewer zoom
- PageCount – Total pages can be read directly from component
- IsSinglePagePreview – Single page mode works
- DocumentContent – byte[] feeding works perfectly
- CustomizeToolbar – Only way to add custom buttons to toolbar
Workaround Strategy
CustomizeToolbar event is used to add custom navigation/zoom buttons.
Manual state tracking (_currentPage, _currentZoom, _viewerZoomLevel) is kept in C#.
Overlay refresh is manually triggered only after button clicks.
protected void OnCustomizeToolbar(ToolbarModel toolbarModel)
{
toolbarModel.AllItems.Clear();
var prevButton = new ToolbarItem
{
Text = "Previous",
IconCssClass = "dx-icon-chevronprev",
Enabled = _currentPage > 1,
Click = async (args) =>
{
if (_currentPage > 1)
{
_currentPage--;
_viewerZoomLevel = _currentZoom / 100d;
await InvokeAsync(StateHasChanged);
await RenderSignatureButtonsAsync();
}
}
};
var nextButton = new ToolbarItem
{
Text = "Next",
IconCssClass = "dx-icon-chevronnext",
Enabled = _currentPage < _totalPages,
Click = async (args) =>
{
if (_currentPage < _totalPages)
{
_currentPage++;
_viewerZoomLevel = _currentZoom / 100d;
await InvokeAsync(StateHasChanged);
await RenderSignatureButtonsAsync();
}
}
};
var zoomInButton = new ToolbarItem
{
IconCssClass = "dx-icon-plus",
Enabled = _currentZoom < 300,
Click = async (args) =>
{
_currentZoom = Math.Min(_currentZoom + 10, 300);
_viewerZoomLevel = _currentZoom / 100d; // 150 -> 1.5
await InvokeAsync(StateHasChanged);
await RenderSignatureButtonsAsync();
}
};
var zoomOutButton = new ToolbarItem
{
IconCssClass = "dx-icon-minus",
Enabled = _currentZoom > 50,
Click = async (args) =>
{
_currentZoom = Math.Max(_currentZoom - 10, 50);
_viewerZoomLevel = _currentZoom / 100d; // 150 -> 1.5
await InvokeAsync(StateHasChanged);
await RenderSignatureButtonsAsync();
}
};
toolbarModel.AllItems.Add(prevButton);
toolbarModel.AllItems.Add(nextButton);
toolbarModel.AllItems.Add(zoomInButton);
toolbarModel.AllItems.Add(zoomOutButton);
}
PageCount reading example (in OnAfterRenderAsync)
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (!_pdfLoaded && _pdfDocumentContent is { Length: > 0 })
{
await Task.Delay(300); // wait for DxPdfViewer to load
if (_pdfViewer is not null && _pdfViewer.PageCount > 0)
{
_totalPages = _pdfViewer.PageCount; // read directly instead of JS
_pdfLoaded = true;
await InvokeAsync(StateHasChanged);
await RenderThumbnailsAsync();
await RenderSignatureButtonsAsync();
}
}
}
Known Acceptable Limitations
- If user scrolls PDF, C#
_currentPagedoes not synchronize - Thumbnail clicks update state but cannot move DevExpress viewer to target page
- Browser zoom gestures do not trigger overlay updates
- Custom toolbar buttons correctly trigger overlay updates
References
- DevExpress official documentation: https://docs.devexpress.com/Blazor/DevExpress.Blazor.PdfViewer.DxPdfViewer
- Verified package:
DevExpress.Blazor.PdfViewerv25.2.3 - Note: AI-suggested APIs (GoToPageAsync, PageNumberChanged, ActivePageIndexChanged, ZoomAsync, ToolbarVisible) are NOT real. Do not use.