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?
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 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