Reputation: 45
I have this method in my components called ClearFiles(string PathName) which I currently call by clicking one of the buttons on the component, but now I'm trying to call of them at once but I cannot figure out how to do this. Calling a single ClearFiles method from the component works perfectly, but I'm not quite sure how to call all these methods at once using the parent class. I have made a button in the parent class with the name of ForceClean which I'm hoping can be pressed to call all of the components clear files function.
I create the components in the parent class using a for loop in my PageFileCleaner.razor file like this:
@foreach (var d in filters)
{
<CompFileFilter FileFilter="d" OnDelete="Delete" ></CompFileFilter>
}
Where filters is a List of type FileFilter which is in the namespace Common.DB. This is how it is declared in the parent class:
private List<FileFilter> filters { get; set; }
And is populated with data from my database using:
using var context = _db.CreateDbContext();
filters = await context.FileFilters.AsNoTracking().ToListAsync();
foreach( var filter in filters)
{
FileFilter f = new FileFilter();
}
And this Parameter (in the child class) is what i use to get the values from that row in the database using FileFilter.Pathname or FileFilter.ID for example:
[Parameter]
public FileFilter FileFilter { get; set; }
Database / FileFilter object class:
namespace Common.DB
{
public class FileFilter
{
[Key]
public int ID { get; set; }
public string TimerChoice { get; set; }
public bool IsLoading;
public string PathName { get; set; } = "";
public string Extension { get; set; }
//public string[] extensionList { get; set; }
...
}
}
The clear files function is in my component/child CompFileFilter.razor file (took the code out for this example because its over a hundred lines of code). I'm creating the components in the parent class and each one will have this ClearFiles() method.
public async Task ClearFiles(string PathName)
{
filtering code...
}
How can I loop through my components from the parent class and call all of there ClearFiles() method?
Upvotes: 2
Views: 441
Reputation: 11302
You can use a dictionary and store the reference of each CompFileFilter
component. Then use the references to call the ClearFiles
method. You can use the ID
property of FileFilter
for the dictionary keys.
PageFileCleaner.razor
@foreach (var d in filters)
{
<CompFileFilter @key="d.ID" @ref="_fileFilterRefs[d.ID]" FileFilter="d" OnDelete="Delete"></CompFileFilter>
}
@code {
private Dictionary<int, CompFileFilter> _fileFilterRefs = new Dictionary<int, CompFileFilter>();
private async Task ForceClean()
{
// Execute ClearFiles one at a time.
foreach (var item in _fileFilterRefs)
{
await item.Value.ClearFiles();
}
// Or execute them in parallel.
//var tasks = _fileFilterRefs.Select(item => Task.Run(item.Value.ClearFiles));
//await Task.WhenAll(tasks);
}
}
ClearFiles
method doesn't need PathName
parameter. You can get the PathName
from the FileFilter
parameter.
CompFileFilter.razor
@code {
[Parameter]
public FileFilter FileFilter { get; set; }
public async Task ClearFiles()
{
var pathName = FileFilter.PathName;
// filtering code...
}
}
Edit:
You should manually update the _fileFilterRefs
dictionary whenever you remove an item from filters
list to keep them synchronized. E.g.
private void Delete(FileFilter fileFilter)
{
_filters.Remove(fileFilter);
_fileFilterRefs.Remove(fileFilter.ID);
}
You should clear the _fileFilterRefs
dictionary whenever you set the filters
list to a new list. E.g.
private async Task RefreshFilters()
{
_fileFilterRefs.Clear();
_filters = await filterService.GetFileFilters();
}
But you don't have to do the same thing when you add a new item to the filters
list (_filters.Add(...)
). In that case it's handled automatically.
In summary:
https://github.com/dotnet/aspnetcore/issues/17361#issuecomment-558138782
Upvotes: 3