Open Kerminator1973 opened 3 months ago
Попробовал собрать BlazorBootstrap - собирается прекрасно, генерирует \blazorbootstrap\bin\Debug\net6.0\BlazorBootstrap.dll
Однако если подключить проект BlazorBootstrap как зависимость, то тестовое приложение не видит пространство имён BlazorBootstrap.
Пошёл по другому пути:
Тем не менее, полноценно код не собрался, попал на ошибку, связанную с проблемой фильтрации:
1>D:\Sources\bbTableCallback\DataTableApp\Pages\FetchData.razor(22,5,22,86): error RZ9985: Multiple components use the tag 'DateInput'. Components: DataTableApp.Pages.DateInput, BlazorBootstrap.DateInput
Временно удалил следующий код:
<div class="mb-3">
<strong>Begin Date:</strong>:
</div>
<div class="mb-3">
<DateInput TValue="DateOnly" @bind-Value="@BeginDate" Placeholder="Enter Date" />
<Button Color="ButtonColor.Primary" Size="Size.Medium" @onclick="ChangeFilter">Set Filter</Button>
</div>
Приложение запустилось на BlazorBootstrap развалился - работала только небольшая часть приложения:
WARNING: Processing source-maps of https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js took longer than 987.7178000000004 ms so we continued execution without waiting for all the breakpoints for the script to be set.Debugging hotkey: Shift+Alt+D (when application has focus)
[0m[48;5;127m[38;5;231mblazor[0m[1m Loaded 23.51 MB resources
[0mThis application was built with linking (tree shaking) disabled. Published applications will be significantly smaller.[0m
Loaded 23.51 MB resources from cache
crit: Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
Unhandled exception rendering component: Could not find 'window.blazorBootstrap.sidebar.initialize' ('sidebar' was undefined).
Error: Could not find 'window.blazorBootstrap.sidebar.initialize' ('sidebar' was undefined).
Однако в варианте с DLL, отладчик входит в код Bootstrap при регистрации сервиса:
builder.Services.AddBlazorBootstrap();
Первая причина - WebAssemblyRenderer не нашёл sidebar:
crit: Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
Unhandled exception rendering component: Could not find 'window.blazorBootstrap.sidebar.initialize' ('sidebar' was undefined).
Error: Could not find 'window.blazorBootstrap.sidebar.initialize' ('sidebar' was undefined).
at https://localhost:7194/_framework/blazor.webassembly.js:1:328
at Array.forEach (<anonymous>)
И тут проблема, похоже, кроется в том, что я не подготовил wwwroot-файлы, или что-то ещё.
Попробую пойти по другому пути - соберу демонстрационное приложение \blazorbootstrap\BlazorBootstrap.Demo.WebAssembly из исходных текстов BlazorBootstrap
Загружается большое приложение, в котором можно поставить контрольные точки в код BlazorBootstrap и попасть в них. В частности, можно выполнять отладку Grid-а: \blazorbootstrap\BlazorBootstrap.Demo.RCL\Components\Pages\Grid\Grid_Demo_23_Multiple_Selection.razor
Т.е. это вариант, в котором можно что-то править в движке BlazorBootstrap, но это пока не отвечает на вопрос, как можно использовать результат сборки изменённого BlazorBootstrap в других приложениях.
Не достаточно импортировать BlazorBootstrap.dll. Необходимо так же скопировать файлы из папки "wwwroot" проекта Blazor.Bootstrap в соответствующую папку нового проекта: "\DataTableApp\wwwroot_content\Blazor.Bootstrap". После этого проект запускается и отладчик позволяет входить из нашего приложения в исходные тексты BlazorBootstrap и выполнять его отладку.
Однако, разметка слегка поехала.
Возможно, причина состоит в том, что не удаётся найти стилистический файл приложения "DataTableApp.styles.css":
Failed to load resource: the server responded with a status of 404 () : DataTableApp.styles.css:1
Нужно попробовать сгенерировать свежее приложение на актуальных шаблонах BlazorBootstrap.
Пытаюсь всё сделать красиво:
Вижу, что появились косяки - часть js-файлов не загрузилась. Т.е. есть какие-то различия. Выбрать в шаблоне целевую платформу нельзя.
Шаблон кривой. В частности, происходит дублирование sln-файлов в двух разных папках:
Новое сгенерированное приложение и переход на .NET 8 проблему с версткой не решили - она стала кривой при переходе обновлении компонентов.
Однако, в моменте на всё это можно забить, т.к. приложение, в целом работает и его можно отлаживать.
Ключевым является метод SaveGridSettingsAsync():
private Task SaveGridSettingsAsync()
{
if (!GridSettingsChanged.HasDelegate)
return Task.CompletedTask;
var settings = new GridSettings { PageNumber = AllowPaging ? gridCurrentState.PageIndex : 0, PageSize = AllowPaging ? pageSize : 0, Filters = AllowFiltering ? GetFilters() : null };
return GridSettingsChanged.InvokeAsync(settings);
}
Через делегата вызывается GridSettingsChanged, которому передаётся объект GridSettings. Гипотетически, в него достаточно просто передать дополнительный параметр - текущий срез данных.
Всё это вызывается из класса Grid:
public partial class Grid<TItem> : BlazorBootstrapComponentBase
Вызов GridSettingsChanged содержит то, что содержит, отражая GridState:
/// <summary>
/// Current grid state (filters, paging, sorting).
/// </summary>
internal GridState<TItem> gridCurrentState = new(1, null);
Включать в GridState текущий срез данных - не очень крутая идея, т.к. это влияет на конкретную сущность GridState.
По идее, должен быть заполнен HashSet selectedItems:
private HashSet<TItem> selectedItems = new();
Но в моём случае, когда я ввожу фильтрацию данных этот параметр равен null. Т.е. он используется для других целей.
Items тоже использовать нельзя, т.е. это срез на предыдущий момент, т.е. до применения фильтрации.
Однако можно поменять местами вызовы в FilterChangedAsync():
internal async Task FilterChangedAsync()
{
...
await SaveGridSettingsAsync();
await RefreshDataAsync(false, token);
}
Гипотетически мы могли бы добавить ещё один параметр - Items:
private Task SaveGridSettingsAsync()
{
if (!GridSettingsChanged.HasDelegate)
return Task.CompletedTask;
var settings = new GridSettings { PageNumber = AllowPaging ? gridCurrentState.PageIndex : 0, PageSize = AllowPaging ? pageSize : 0, Filters = AllowFiltering ? GetFilters() : null,
Items = this.items };
return GridSettingsChanged.InvokeAsync(settings);
}
Однако это не сработает поскольку items - это шаблонный контейнер, а класс GridSettings обычный Poco-класс, т.е. мы не можем просто добавить ссылку, т.к. нам нужна специализация - тип Grid-а.
Костыльное решение, которые мы можем сделать без перепроектирования библиотеки - это изменить сигнатуру GridSettingsChanged и добавить ещё один параметр - ссылку на Item, с учётом специализации.
return GridSettingsChanged.InvokeAsync(settings);
Но на самом деле, это сложно сделать, т.е. делегат и так уже определён, как шаблон:
[Parameter]
public EventCallback<GridSettings> GridSettingsChanged { get; set; }
Можно, конечно, вытащить отдельный метод для доступа к items, но это совсем костыль, не по парадигме библиотеки.
Вступил в переписку с разработчиком Blazor Bootstrap, ожидается решение этой проблемы в начале мая.
Приостанавливаю исследования до 10 мая.