When the user renames a folder, the TreeView foes not refresh to display the new folder name.
The test page below is based on the FileManager Events example.
A possible workaround is to recreate the FileManager in the OnUpdate handler:
@using System.IO
@if (ShouldRenderFileManager)
{
<TelerikFileManager @ref="@FileManagerRef"
Data="@Files"
@bind-Path="@DirectoryPath"
View="@CurrentView"
ViewChanged="@OnViewChanged"
Height="400px"
OnCreate="@OnCreateHandler"
OnUpdate="@OnUpdateHandler"
OnDelete="@OnDeleteHandler"
OnModelInit="@OnModelInitHandler"
OnDownload="@OnDownloadHandler"
SelectedItems="@SelectedItems"
SelectedItemsChanged="@((IEnumerable<FlatFileEntry> selectedFiles) => OnSelect(selectedFiles))">
</TelerikFileManager>
}
@foreach (var item in Files)
{
<div>@item.Name</div>
}
@code {
private bool ShouldRenderFileManager { get; set; } = true;
private TelerikFileManager<FlatFileEntry>? FileManagerRef { get; set; }
private List<FlatFileEntry> Files { get; set; } = new();
private string DirectoryPath { get; set; } = string.Empty;
private IEnumerable<FlatFileEntry> SelectedItems { get; set; } = new List<FlatFileEntry>();
private FileManagerViewType CurrentView { get; set; }
private void OnViewChanged(FileManagerViewType newView)
{
CurrentView = newView;
}
private async Task OnCreateHandler(FileManagerCreateEventArgs args)
{
var newFolder = args.Item as FlatFileEntry;
var parent = GetParent(newFolder, DirectoryPath);
newFolder.Id = "20";
newFolder.ParentId = parent.Id;
newFolder.Name = "New folder";
newFolder.IsDirectory = true;
newFolder.HasDirectories = false;
newFolder.DateCreated = DateTime.Now;
newFolder.DateCreatedUtc = DateTime.Now;
newFolder.DateModified = DateTime.Now;
newFolder.DateModifiedUtc = DateTime.Now;
newFolder.Path = Path.Combine(DirectoryPath, newFolder.Name);
newFolder.Extension = null;
var parentDirectory = GetDirectory(DirectoryPath) ?? GetParent(newFolder, DirectoryPath);
if (parentDirectory != null)
{
// Simulate add to the file system.
newFolder.ParentId = parentDirectory.Id;
Files.Add(newFolder);
parentDirectory.HasDirectories = Files.Count(x => x.ParentId == parentDirectory.Id) > 0;
}
else
{
// Create a folder in the root directory.
Files.Add(newFolder);
}
RefreshData();
}
private FlatFileEntry GetDirectory(string path)
{
var directory = Files.FirstOrDefault(x => x.IsDirectory && x.Path == path);
return directory;
}
private FlatFileEntry GetParent(FlatFileEntry currItem, string currDirectory)
{
var parentItem = Files
.FirstOrDefault(x => x.IsDirectory && x.Path == currDirectory);
return parentItem;
}
private async Task OnUpdateHandler(FileManagerUpdateEventArgs args)
{
var item = args.Item as FlatFileEntry;
if (item.IsDirectory)
{
var name = item.Name ?? string.Empty;
var updatedItem = Files.FirstOrDefault(x => x.Id == item.Id);
updatedItem.Name = item.Name;
updatedItem.Path = Path.Combine(DirectoryPath, name);
ShouldRenderFileManager = false;
await Task.Delay(1);
ShouldRenderFileManager = true;
}
else
{
// The name property is updated, but also update the path to the file.
var name = item.Name ?? string.Empty;
var extension = item.Extension ?? string.Empty;
var fullName = extension.Length > 0 && name.EndsWith(extension) ?
name : $"{name}{extension}";
var updatedItem = Files.FirstOrDefault(x => x.Id == item.Id);
updatedItem.Name = item.Name;
updatedItem.Path = Path.Combine(DirectoryPath, fullName);
Console.WriteLine(updatedItem.Path);
}
}
private async Task OnDownloadHandler(FileManagerDownloadEventArgs args)
{
var selectedItem = args.Item as FlatFileEntry;
// The Filemanager does not have the actual file.
// Obtain the file contents, based on args.Item, and set the event arguments:
//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);
FlatFileEntry actualFile = (FlatFileEntry)args.Item;
string dummyFileContent = $"This file is a dummy version of {actualFile.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";
}
private async Task OnDeleteHandler(FileManagerDeleteEventArgs args)
{
var currItem = args.Item as FlatFileEntry;
var itemToDelete = Files.FirstOrDefault(x => x.Id == currItem.Id);
Files.Remove(itemToDelete);
RefreshData();
}
private FlatFileEntry OnModelInitHandler()
{
var item = new FlatFileEntry();
item.Name = $"New folder";
item.Size = 0;
item.Path = Path.Combine(DirectoryPath, item.Name);
item.IsDirectory = true;
item.HasDirectories = false;
item.DateCreated = DateTime.Now;
item.DateCreatedUtc = DateTime.Now;
item.DateModified = DateTime.Now;
item.DateModifiedUtc = DateTime.Now;
return item;
}
private void OnSelect(IEnumerable<FlatFileEntry> selectedFiles)
{
// Update the view model.
SelectedItems = selectedFiles;
}
private void RefreshData()
{
Files = new List<FlatFileEntry>(Files);
}
protected override async Task OnInitializedAsync()
{
Files = await GetFlatFileEntries();
}
public class FlatFileEntry
{
public string Id { get; set; }
public string ParentId { get; set; }
public string Name { get; set; }
public long Size { get; set; }
public string Path { get; set; }
public string Extension { get; set; }
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; }
}
// the next lines are hardcoded data generation so you can explore the FileManager freely
private async Task<List<FlatFileEntry>> GetFlatFileEntries()
{
var workFiles = new FlatFileEntry()
{
Id = "1",
ParentId = null,
Name = "Work Files",
IsDirectory = true,
HasDirectories = true,
DateCreated = new DateTime(2022, 1, 2),
DateCreatedUtc = new DateTime(2022, 1, 2),
DateModified = new DateTime(2022, 2, 3),
DateModifiedUtc = new DateTime(2022, 2, 3),
Path = Path.Combine("files"),
Size = 3 * 1024 * 1024
};
var Documents = new FlatFileEntry()
{
Id = "2",
ParentId = workFiles.Id,
Name = "Documents",
IsDirectory = true,
HasDirectories = false,
DateCreated = new DateTime(2022, 1, 2),
DateCreatedUtc = new DateTime(2022, 1, 2),
DateModified = new DateTime(2022, 2, 3),
DateModifiedUtc = new DateTime(2022, 2, 3),
Path = Path.Combine(workFiles.Path, "documents"),
Size = 1024 * 1024
};
var Images = new FlatFileEntry()
{
Id = "3",
ParentId = workFiles.Id,
Name = "Images",
IsDirectory = true,
HasDirectories = false,
DateCreated = new DateTime(2022, 1, 2),
DateCreatedUtc = new DateTime(2022, 1, 2),
DateModified = new DateTime(2022, 2, 3),
DateModifiedUtc = new DateTime(2022, 2, 3),
Path = Path.Combine(workFiles.Path, "images"),
Size = 2 * 1024 * 1024
};
var files = new List<FlatFileEntry>()
{
workFiles,
Documents,
Images
};
return files;
}
}
Currently, only the "Download" option has an icon and this is not consistent:
The need to right-click a file to be able to download it is a bit less intuitive.
I would like to be able to download a file by double-clicking it, or, more generic, to be able to add a double click handler so I can decide what to do with it.
Greetings.
I was using the FileManager recently and wanted to make sure the user could only select a single file. I was expecting a parameter to configure that but I didn't find any. I was able to bypass the issue by acting on the value reported by the component but I found it a bit inconvenient.
I think it might be interesting if we could:
What do you think?
Greetings.
I was using the FileManager component for a project and wanted to disable some operations since in my use case, it must not be possible to do them. But I was surprized to notice that this apparently cannot be done. So I suggest to add boolean parameters that will allow to disable the following features:
Of course, the goal here would be to render the user interface accordingly. E.g., if deletion is disabled:
When using the FileManager and navigating through directories, the Breadcrumb does not show the path.
Reproduction: https://blazorrepl.telerik.com/GdOCYQki12iTAeWd34
When the FileManager is placed in a Window/Dialog, the ContextMenu does not open.
---
ADMIN EDIT
---
Essentially, the ContextMenu is rendered but appears behind the Window/Dialog and thus it is not visible. The issue is z-index related and a possible workaround is to increase the z-index of the ContextMenu to ensure it will be visible.
Hello,
Nice work on the FileManager component, this will be incredibly useful. I would like to use this control in an Open File Dialog and the only thing I'm missing to support that is what is the selected item in the listview. If I could bind that selection then I could enable/disable my Ok button and provide the selected item(s) when the user hit's ok. Is there a way to access this information?
Thanks,
-Andy
Would like to be able to change / recall State of expanded / collapsed items in FileManager, similar to how we can with the Grid component using Groups.
On refreshing data from the database, the entire File Manager reverts to all items collapsed, which will be annoying for end users.
State management could also deal with the default view (Details vs Icons) as requested elsewhere for this component.
For true load on demand, the OnRead event should be triggered for: