()
- {
- workFiles,
-
- Documents,
- specification,
- report,
+### OnEdit
- Images,
- dashboardDesign,
- gridDesign
- };
+The `OnEdit` event fires when the user is about to enter edit mode for an existing item. Its event handler receives the updated `FileManagerEditEventArgs` as an argument.
- return await Task.FromResult(files);
- }
-}
-````
+### OnUpdate
-## Other Events
+The `OnUpdate` event fires when a file is updated (rename finishes). Its event handler receives the updated `FileManagerUpdateEventArgs` as an argument.
-### OnModelInit
+## OnDownload
-The `OnModelInit` event fires when a new instance of the model is about to be created. Handle this event to allow the creation of a new folder/file. Provide an instance of the model that the component is bound to and include the desired properties (name, path, date of creation and more). See the [example](#example).
+The `OnDownload` event fires before a file download starts. The event is cancellable. The event handler argument is an `FileManagerDownloadEventArgs` object. See the [example](#example).
-### OnDownload
+### MIME Type
-The `OnDownload` event fires before a file download starts. The event is cancellable. The event handler argument is an `FileManagerDownloadEventArgs` object. See the [example](#example).
+The `FileManagerDownloadEventArgs` event argument has a `MimeType` property, which is `null` when the `OnDownload` event fires. .NET does not provide a built-in MIME type tool, so the application must set the correct MIME type, depending on the file extension or content. Consider [`Microsoft.AspNetCore.StaticFiles`](https://github.com/dotnet/aspnetcore/blob/main/src/Middleware/StaticFiles/src/FileExtensionContentTypeProvider.cs) or a similar tool.
-#### Downloading Large Files
+### Downloading Large Files
The files are downloaded with the help of a Base64 data URL, which is sent to the browser through `JSInterop`. JavaScript code generates an `` tag with an [object URL](https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL_static) on the web page and the tag is clicked programmatically, so that the browser shows its **Save File** dialog.
@@ -341,7 +65,7 @@ Large files (tens or hundreds of megabytes) may hit the browser's max data URL l
>tip You can also vote for the [FileManager feature request to expose a Proxy Url](https://feedback.telerik.com/blazor/1633629) for serving files from the server to the browser.
-#### Downloading Server Files in WebAssembly Apps
+### Downloading Server Files in WebAssembly Apps
A FileManager in a WebAssembly app usually displays files from a remote server. In such cases, use the following download approach:
@@ -349,15 +73,31 @@ A FileManager in a WebAssembly app usually displays files from a remote server.
1. The server returns the file content.
1. The `OnDownload` handler puts the returned file content to a `MemoryStream` and assigns it to `args.Stream`.
-### PathChanged
+## OnModelInit
+
+The `OnModelInit` event fires when a new instance of the model is about to be created. Handle this event to allow the creation of a new folder/file. Provide an instance of the model that the component is bound to and include the desired properties (name, path, date of creation and more). See the [example](#example).
+
+## OnRead
+
+The `OnRead` event is an alternative way to provide the FileManager with data, instead of the `Data` parameter. The event fires when the FileManager is initialized. The event handler receives a `FileManagerReadEventArgs` object as an argument.
+
+Use the `OnRead` event if you want to load chunks of FileManager data on demand. The following API members are required:
+
+* `PathChanged` event
+* `Rebind()` method
+* `OnRead` event
+
+For more information, refer to [How to Load FileManager File Data on Demand](slug:filemanager-kb-load-file-data-on-demand).
+
+## PathChanged
The `PathChanged` event fires when the user navigates to a different folder through the TreeView or by double-clicking a folder item in the [FileManager View](slug:filemanager-views). The event handler receives the new path as a `string` argument.
-### SelectedItemsChanged
+## SelectedItemsChanged
The `SelectedItemChanged` event fires every time the user clicks on a new file/folder in the main pane of the FileManager. You can use it with one-way binding of the `SelectedItems` parameter to respond to user selection.
-### ViewChanged
+## ViewChanged
The `ViewChanged` event fires when the user toggles between the [two FileManager views (`Grid` and `ListView`)](slug:filemanager-views). If you are using the event, make sure to update the value of the `View` parameter, otherwise the user action will have no effect.
@@ -477,24 +217,31 @@ The `ViewChanged` event fires when the user toggles between the [two FileManager
private async Task OnDownloadHandler(FileManagerDownloadEventArgs args)
{
- var selectedItem = args.Item as FlatFileEntry;
+ var downloadedFile = (FlatFileEntry)args.Item;
// The Filemanager does not have the actual file.
- // Obtain the file contents, based on args.Item, and set the event arguments:
+ // Obtain the file contents, based on args.Item, and set the event arguments.
+
+ // Get the full file path
+ //string filePathWithoutStartSeparator = downloadedFile.Path.IndexOf(Path.DirectorySeparatorChar) == 0 ? downloadedFile.Path.Substring(1) : downloadedFile.Path;
+ //string fullFilePath = Path.Combine(BasePath, filePathWithoutStartSeparator);
- //args.Stream = the file stream of the actual selected file;
- //args.MimeType = the MIME type of the actual file;
- //args.FileName = the file name that the browser will receive (optional);
+ // Create a MemoryStream with the file contents
+ //byte[] fileBytes = await System.IO.File.ReadAllBytesAsync(fullFilePath);
+ //MemoryStream fileStream = new(fileBytes);
- FlatFileEntry actualFile = (FlatFileEntry)args.Item;
+ // Set the event arguments
+ //args.FileName = string.Concat(downloadedFile.Name, downloadedFile.Extension);
+ //args.MimeType = "application/octet-stream";
+ //args.Stream = fileStream;
await Task.Delay(1); // simulate async operation
- string dummyFileContent = $"This file is a dummy version of {actualFile.Name}. It was downloaded with the Telerik Blazor FileManager.";
+ string dummyFileContent = $"This file is a dummy version of {downloadedFile.Name}. It was downloaded with the Telerik Blazor FileManager.";
byte[] dummyFileBuffer = System.Text.Encoding.UTF8.GetBytes(dummyFileContent);
args.Stream = new MemoryStream(dummyFileBuffer);
args.MimeType = "text/plain";
- args.FileName = $"filemanager-{actualFile.Name}-{DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss")}.txt";
+ args.FileName = $"filemanager-{downloadedFile.Name}-{DateTime.Now.ToString("HH-mm-ss")}.txt";
}
private async Task OnDeleteHandler(FileManagerDeleteEventArgs args)
diff --git a/knowledge-base/filemanager-load-file-data-on-demand.md b/knowledge-base/filemanager-load-file-data-on-demand.md
new file mode 100644
index 000000000..23168a57c
--- /dev/null
+++ b/knowledge-base/filemanager-load-file-data-on-demand.md
@@ -0,0 +1,207 @@
+---
+title: Load FileManager File Data on Demand
+description: Learn how to load the files from the currently selected folder in the FileManager for better performance.
+type: how-to
+page_title: How to Load FileManager File Data on Demand
+slug: filemanager-kb-load-file-data-on-demand
+tags: telerik, blazor, filemanager
+ticketid: 1677209, 1665314, 1608943, 1606421, 1566070
+res_type: kb
+---
+
+## Environment
+
+
+
+
+ Product |
+ FileManager for Blazor |
+
+
+
+
+## Description
+
+This KB article answers the following questions:
+
+* How to load FileManager files on demand?
+* How to lazy load the FileManager data?
+* How to bind the FileManager only to the files from the currently selected folder?
+* How to implement data virtualization for the Telerik FileManager for Blazor?
+* How to dynamically add folders and files to the FileManager data?
+
+## Solution
+
+1. Subscribe the to the [FileManager `PathChanged` event](slug:filemanager-events#pathchanged).
+1. Subscribe to the [FileManager `OnRead` event](slug:filemanager-events#onread).
+1. Obtain the [FileManager `@ref` (component instance)](slug:filemanager-overview#reference-and-methods).
+1. Call the FileManager `Rebind()` method in the `PathChanged` event handler.
+1. Load all folders for the FileManager TreeView and the files from the current folder. Set this collection to [`args.Data` in the `OnRead` handler](slug:common-features-data-binding-onread#event-argument).
+
+>caption Load FileManager file data on demand using OnRead and PathChanged
+
+````RAZOR
+@using System.IO
+@using Telerik.DataSource.Extensions
+
+
+ Total folder and file count: @FlatData.Count;
+ Folders loaded: @FoldersLoadedCount;
+ Files loaded: @FilesLoadedCount
+
+
+Path: @FlatDirectoryPath
+
+
+
+
+@code {
+ private TelerikFileManager? FileManagerRef { get; set; }
+ private List FlatData { get; set; } = new List();
+
+ private readonly string RootPath = string.Empty;
+ private string FlatDirectoryPath { get; set; } = string.Empty;
+
+ private int FoldersLoadedCount { get; set; }
+ private int FilesLoadedCount { get; set; }
+
+ private int FolderLevelCount { get; set; } = 5;
+ private int FilesInFolderMinCount { get; set; } = 3;
+ private int FilesInFolderMaxCount { get; set; } = 24;
+ private int FoldersInFolderCount { get; set; } = 3;
+ private int FolderNameCounter { get; set; }
+ private readonly List FileExtensions = new() {
+ ".txt", ".pdf", ".docx", ".xlsx", ".png", ".jpg", ".gif", ".zip", ".css", ".html", ".mp3", ".mpg"
+ };
+
+ private void FileManagerPathChanged(string newPath)
+ {
+ FlatDirectoryPath = newPath;
+
+ FileManagerRef?.Rebind();
+ }
+
+ private async Task OnFileManagerRead(FileManagerReadEventArgs args)
+ {
+ var allFoldersAndVisibleFiles = FlatData.Where(x =>
+ // all folders
+ x.IsDirectory ||
+ // all files if in the root folder
+ (FlatDirectoryPath == RootPath && x.Path.IndexOf(Path.DirectorySeparatorChar) == x.Path.LastIndexOf(Path.DirectorySeparatorChar)) ||
+ // all files if in another folder
+ x.Path.Replace(string.Concat(Path.DirectorySeparatorChar, x.Name, x.Extension), string.Empty) == FlatDirectoryPath);
+
+ args.Data = allFoldersAndVisibleFiles;
+ args.Total = allFoldersAndVisibleFiles.Count();
+
+ FoldersLoadedCount = allFoldersAndVisibleFiles.Where(x => x.IsDirectory).Count();
+ FilesLoadedCount = allFoldersAndVisibleFiles.Count() - FoldersLoadedCount;
+
+ await Task.Delay(1); // simulate async operation
+ }
+
+ protected override async Task OnInitializedAsync()
+ {
+ await Task.CompletedTask;
+
+ FlatDirectoryPath = RootPath;
+
+ FlatData = LoadFlatDataAsync();
+
+ await base.OnInitializedAsync();
+ }
+
+ private List LoadFlatDataAsync()
+ {
+ List data = new List();
+
+ string rootDataPath = string.IsNullOrEmpty(RootPath) ? "/" : RootPath;
+
+ PopulateChildren(data, null, rootDataPath, 1);
+
+ return data;
+ }
+
+ private void PopulateChildren(List data, string? parentId, string parentPath, int level)
+ {
+ var rnd = Random.Shared;
+ var filesInCurrentFolder = rnd.Next(FilesInFolderMinCount, FilesInFolderMaxCount);
+
+ for (int i = 1; i <= filesInCurrentFolder; i++)
+ {
+ string itemId = Guid.NewGuid().ToString();
+ string itemExtension = FileExtensions[rnd.Next(0, FileExtensions.Count)];
+ string itemName = $"{itemExtension.Substring(1)}-file-{(FolderNameCounter != default ? string.Concat(FolderNameCounter, "-") : string.Empty)}{i}";
+ string itemPath = Path.Combine(parentPath, string.Concat(itemName, itemExtension));
+
+ data.Add(new FlatFileEntry()
+ {
+ Id = itemId,
+ ParentId = parentId,
+ Name = itemName,
+ IsDirectory = false,
+ HasDirectories = false,
+ DateCreated = DateTime.Now,
+ DateCreatedUtc = DateTime.Now.ToUniversalTime(),
+ DateModified = DateTime.Now,
+ DateModifiedUtc = DateTime.Now.ToUniversalTime(),
+ Path = itemPath,
+ Extension = itemExtension,
+ Size = rnd.Next(1_000, 3_000_000)
+ });
+ }
+
+ if (level < FolderLevelCount)
+ {
+ for (int i = 1; i <= FoldersInFolderCount; i++)
+ {
+ var itemId = Guid.NewGuid().ToString();
+ var itemName = $"folder-{++FolderNameCounter}";
+ var itemPath = Path.Combine(parentPath, itemName);
+
+ data.Add(new FlatFileEntry()
+ {
+ Id = itemId,
+ ParentId = parentId,
+ Name = itemName,
+ IsDirectory = true,
+ HasDirectories = level < FolderLevelCount - 1,
+ DateCreated = DateTime.Now,
+ DateCreatedUtc = DateTime.Now.ToUniversalTime(),
+ DateModified = DateTime.Now,
+ DateModifiedUtc = DateTime.Now.ToUniversalTime(),
+ Path = itemPath,
+ Size = rnd.Next(100_000, 10_000_000)
+ });
+
+ PopulateChildren(data, itemId, itemPath, level + 1);
+ }
+ }
+ }
+
+ public class FlatFileEntry
+ {
+ public string Id { get; set; } = Guid.NewGuid().ToString();
+ public string? ParentId { get; set; }
+ public string Name { get; set; } = string.Empty;
+ public long Size { get; set; }
+ public string Path { get; set; } = string.Empty;
+ public string Extension { get; set; } = string.Empty;
+ public bool IsDirectory { get; set; }
+ public bool HasDirectories { get; set; }
+ public DateTime DateCreated { get; set; }
+ public DateTime DateCreatedUtc { get; set; }
+ public DateTime DateModified { get; set; }
+ public DateTime DateModifiedUtc { get; set; }
+ }
+}
+````
+
+## See Also
+
+* [FileManager Events](slug:filemanager-events)