我尝试在 Blazor Web 应用和服务器中使用 QuickGrid。但代码总是显示“程序集缺失”。我按照文档中的所有步骤操作并应用了它,但仍然显示
命名空间dotnet 添加包 Microsoft.AspNetCore.Components.QuickGrid中缺少 QuickGrid
我已经安装了该 nuget 包:
@using Microsoft.AspNetCore.Components.QuickGrid
我需要根据单选按钮选择显示不同的组件,因此我使用此处InputRadioGroup
描述的方法。
当选择任一选项时,页面会重新渲染,并显示正确的组件,但InputRadioGroup
会再次重新渲染,并且不会保留选择。我尝试过放入, InputRadioGroup
但<EditForm Model="ColorInt"
发生了同样的事情。我甚至尝试过这种checked="@(ColorInt == 1)"
方法,但它也不起作用。这是一个已报告的错误,已在 .NET 7 中解决,但它仍然发生在我身上。
<InputRadioGroup Name="color" @bind-Value="ColorInt">
Colors:
<div style="margin-bottom:5px">
<div>
<label>
<InputRadio Name="color" Value="1" checked="@(ColorInt == 1)" />
Red
</label>
</div>
<div>
<label>
<InputRadio Name="color" Value="2" checked="@(ColorInt == 2)" />
Green
</label>
</div>
<div>
<label>
<InputRadio Name="color" Value="3" checked="@(ColorInt == 3)" />
Blue
</label>
</div>
</div>
</InputRadioGroup>
@switch (ColorInt)
{
case 1: { <red /> break; }
case 2: { <green/> break; }
case 3: { <blue/> break; }
}
@code {
private int ColorInt{ get; set; } = 1;
}
PS 这只是我的愚蠢行为...因为需要编辑我的实际代码,所以我从未检查过这一点。我的代码Value
实际上来自一个静态类MagicStrings
,该类保存了我整个应用程序的一些const
值。
<InputRadio Name="color" Value="@MagicStrings.RedColor" />
现在MagicStrings.RedColor
类型是byte
public const byte RedColor = 1;
@code {
private int ColorInt{ get; set; } = @MagicStrings.RedColor; // which was byte
}
我们在 VS 2022 中有一个 .NET 8 和 C# Blazor 项目,其中包含许多 QuickGrids。
我想使用 来放置PropertyColumn
的标题文本的 HTML 和样式HeaderTemplate
,这将覆盖该Title
字段。但我不知道如何使用HeaderTemplate
。
我的 QuickGrid 标记如下所示:
<PropertyColumn
Property="f => f.TXT_NAME"
HeaderTemplate="<TemplateHeader>Missouri</TemplateHeader>"
Sortable="false" Class="itemName" />
我已在 Google 上搜索了指定/利用该HeaderTemplate
功能的正确方法的示例,但找不到任何示例。您在上面的代码中看到的是关于如何使用的无效猜测HeaderTemplate
。
当我输入代码时HeaderTemplate
,VS 2022 会立即跟进=""
-- 暗示应该输入一些文本。但是……我尝试了各种方法,你可以看到我尝试提供一个包含渲染片段的组件 -- 但编译时不会出现错误
无效的表达式术语“<”
我陷入困境。
渲染片段组件标记和代码如下:
<div class="text-danger fst-italic fw-bold">
@ChildContent
</div>
@code {
#pragma warning disable CS8618
[Parameter] public RenderFragment? ChildContent { get; set; }
#pragma warning restore CS8618
}
欢迎您提出解决方案、评论和问题。
谢谢。
我有一个 ASP.NET Core Web API 项目作为后端,还有一个 Blazor Web 程序集作为前端。
Web API 可ProductController
返回 JSON 数据(产品、组等)。Blazor 应用使用该 API。
ProductService
我在 Blazor 端创建。ProductService
获取HttpClient
构造函数注入并向 API 发送请求。这就是问题所在——我收到 404 NotFound 错误。当我使用注入HttpClient
或直接在页面上创建它时,它可以工作(请参阅下面显示的代码)。
如果我在浏览器中输入 API URL,我会得到数据(产品目录)。我HttpClient
按照 Microsoft在文章中所说的进行初始化。请帮助解决这个问题。
这是 Blazor 初始化代码:
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");
builder.Configuration.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
var appSettings = builder.Configuration.Get<AppSettings>();
builder.Services.AddSingleton<AppSettings>(appSettings);
builder.Services.AddBlazoredLocalStorage();
builder.Services.AddHttpClient("Shop.WebApi", client => client.BaseAddress =
new Uri(appSettings.ApiBaseUri))
.AddHttpMessageHandler<CustomAuthorizationMessageHandler>();
builder.Services.AddScoped<CustomAuthorizationMessageHandler>();
builder.Services.AddScoped(sp => sp.GetRequiredService<IHttpClientFactory>().CreateClient("Shop.WebApi"));
builder.Services.AddApiAuthorization();
builder.Services.AddScoped<CustomAuthenticationStateProvider>();
builder.Services.AddScoped<AuthenticationStateProvider>(
provider => provider.GetRequiredService<CustomAuthenticationStateProvider>());
builder.Services.AddScoped<AuthService>();
builder.Services.AddHttpClient<IProductService, HttpProductService>(client =>
{
client.BaseAddress = new Uri(appSettings.ApiBaseUri);
}).AddHttpMessageHandler<CustomAuthorizationMessageHandler>();
await builder.Build().RunAsync();
这是产品目录页面:
@inject IProductService ProductService
@inject HttpClient TheHttpClient
...
protected override async Task OnInitializedAsync()
{
try
{
// this works
_ProductCatalog = await TheHttpClient.GetFromJsonAsync<ProductCatalog>("api/Product/GetProductCatalog");
// this doesn't work
//await LoadProductCatalogAsync();
}
catch (Exception ex)
{
Console.WriteLine("An error occurred while initializing the page: " + ex.Message);
}
}
private async Task LoadProductCatalogAsync()
{
try
{
_ProductCatalog = await ProductService.GetProductCatalog();
}
catch (Exception ex)
{
Console.WriteLine("An error occurred while loading the product catalog: " + ex.Message);
}
}
产品服务:
public class HttpProductService : IProductService
{
public HttpProductService(HttpClient httpClient)
{
TheHttpClient = httpClient;
}
public async Task<ProductCatalog> GetProductCatalog()
{
var response = await TheHttpClient.GetAsync($"{GetApiBaseUri()}");
if (response.IsSuccessStatusCode)
{
return await response.Content.ReadFromJsonAsync<ProductCatalog>();
}
return new ProductCatalog();
}
protected virtual string GetApiBaseUri() => $"api/Product";
protected HttpClient TheHttpClient { get; }
}
我正在尝试使用 FluentDataGrid 显示数据,但出现了非常奇怪的行为。问题:
这是我的代码。我使用@rendermode = InteractiveAssembly。
@rendermode InteractiveWebAssembly
@inject HttpClientService httpClientService
<FluentDataGrid Items="RolesData?.Data?.AsQueryable()"
TGridItem="GetRoles.Response"
Pagination="paginationState"
ShowHover="true"
MultiLine="true"
Loading="@gridLoader">
<PropertyColumn Property="@(c => c.Name)" Sortable="false" />
<TemplateColumn Title="Permissions">
<p>@context.PermissionCount permissions assigned</p>
</TemplateColumn>
<TemplateColumn Title="Assigned To">
<p>@context.AssignedTo uers</p>
</TemplateColumn>
<TemplateColumn Title="Actions">
@if (context.IsPrimary == false)
{
<FluentButton aria-label="Edit item" IconEnd="@(new Icons.Regular.Size16.Edit())" OnClick="() => OnEditClick(context.Id)" />
<FluentButton aria-label="Delete item" IconEnd="@(new Icons.Regular.Size16.Delete())" OnClick="() => OnDeleteClick(context.Id)" />
}
</TemplateColumn>
</FluentDataGrid>
<FluentPaginator State="@paginationState" CurrentPageIndexChanged="OnCurrentPageIndexChanged" />
这是我的组件。我最初在 OnAfterRenderAsync 上获取数据
private GetRoles.Request request = new GetRoles.Request();
private Pagination.Response<IEnumerable<GetRoles.Response>>? RolesData;
PaginationState paginationState = new PaginationState { ItemsPerPage = 10 };
bool gridLoader;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
await GetRoles();
}
}
private async Task GetRoles()
{
gridLoader = true;
StateHasChanged();
request.Page = paginationState.CurrentPageIndex;
request.PageSize = paginationState.ItemsPerPage;
var roleDataResponse = await httpClientService.GetAsync<Pagination.Response<IEnumerable<GetRoles.Response>>>("/api/roles", request);
if (roleDataResponse != null)
{
RolesData = roleDataResponse;
await paginationState.SetTotalItemCountAsync(roleDataResponse.TotalRecords);
}
gridLoader = false;
StateHasChanged();
Console.WriteLine($"CurrentPageIndex: {paginationState.CurrentPageIndex}");
Console.WriteLine($"LastPageIndex: {paginationState.LastPageIndex}");
Console.WriteLine($"TotalItemCount: {paginationState.TotalItemCount}");
}
处理分页按钮点击的事件是
async void OnCurrentPageIndexChanged(int index)
{
await paginationState.SetCurrentPageIndexAsync(index);
await GetRoles();
}
这是 API 返回的数据
{
"totalRecords": 11,
"data": [
{
"id": "Dy9dkGzW",
"name": "Test 9",
"permissionCount": 2,
"assignedTo": 0,
"isPrimary": false
},
{
"id": "eV9ablPg",
"name": "Test 8",
"permissionCount": 2,
"assignedTo": 0,
"isPrimary": false
},
{
"id": "X892olBV",
"name": "Test 7",
"permissionCount": 10,
"assignedTo": 0,
"isPrimary": false
},
{
"id": "8e7V896p",
"name": "Test 6",
"permissionCount": 1,
"assignedTo": 0,
"isPrimary": false
},
{
"id": "1VGx2l5Q",
"name": "Test 5",
"permissionCount": 4,
"assignedTo": 0,
"isPrimary": false
},
{
"id": "5Y7Qq7Bk",
"name": "Test 4",
"permissionCount": 9,
"assignedTo": 0,
"isPrimary": false
},
{
"id": "O8l1wGqx",
"name": "Test 3",
"permissionCount": 2,
"assignedTo": 0,
"isPrimary": false
},
{
"id": "Y8Gb39Bq",
"name": "Test 2",
"permissionCount": 3,
"assignedTo": 0,
"isPrimary": false
},
{
"id": "QY7BV7OV",
"name": "Test 1",
"permissionCount": 2,
"assignedTo": 0,
"isPrimary": false
},
{
"id": "ZYG8o71v",
"name": "Finance",
"permissionCount": 8,
"assignedTo": 0,
"isPrimary": false
}
]
}
如您所见,这里的“totalRecords”为 11。分页应该显示总记录数为 11,并且应该有 2 页,但它向我显示了这个
如果我将“await paginationState.SetTotalItemCountAsync(roleDataResponse.TotalRecords);”移到方法的末尾,它会正确设置总项目数,并且分页按钮不会被禁用,但是当我单击下一个按钮时,事件处理程序在“索引”中获取 0。
我是不是漏掉了什么,或者做错了什么?任何帮助都将不胜感激。
先感谢您。
我在 Blazor Server 应用程序中使用 Syncfusion 的 SfTextBox 组件。我已将其绑定@bind-Value
到模型中的属性,并添加了ValueChange
事件以添加其他逻辑。
但是,ValueChange
事件未触发,并且绑定属性仍然为空。
<SfTextBox @bind-value=@Value
Placeholder=@Placeholder
Enabled=@IsEnabled
[email protected]
CssClass="" />
public partial class SignInComponent : ComponentBase
{
[Inject]
public IIdentityViewService IdentityViewService { get; set; }
[Inject]
public AuthenticationStateProvider AuthStateProvider { get; set; }
public ComponentState State { get; set; }
public IdentityComponentException Exception { get; set; }
public SignInView SignInView { get; set; }
public TextBoxBase SignInEmailTextBox { get; set; }
public TextBoxBase SignInPasswordTextBox { get; set; }
public ButtonBase SubmitButton { get; set; }
public SpinnerBase Spinner { get; set; }
protected override void OnInitialized()
{
SignInView = new SignInView();
State = ComponentState.Content;
}
}
public partial class TextBoxBase : ComponentBase
{
[Parameter]
public string Value { get; set; }
[Parameter]
public string Placeholder { get; set; }
[Parameter]
public string CssClass { get; set; }
[Parameter]
public EventCallback<string> ValueChanged { get; set; }
[Parameter]
public bool IsDisabled { get; set; }
public bool IsEnabled => IsDisabled is false;
public async Task SetValue(string value)
{
this.Value = value;
await ValueChanged.InvokeAsync(this.Value);
}
private Task OnValueChanged(ChangeEventArgs changeEventArgs)
{
this.Value = changeEventArgs.Value.ToString();
//InvokeAsync(StateHasChanged);
return ValueChanged.InvokeAsync(this.Value);
}
public void Disable()
{
this.IsDisabled = true;
InvokeAsync(StateHasChanged);
}
public void Enable()
{
this.IsDisabled = false;
InvokeAsync(StateHasChanged);
}
}
<div class="py-6 flex flex-col gap-5">
<div>
<TextBoxBase
@ref=@SignInEmailTextBox
@[email protected]
Placeholder="Your email ?"
CssClass="w-full py-3 px-6 ring-1 ring-gray-300 rounded-xl placeholder-gray-600 bg-transparent transition disabled:ring-gray-200 disabled:bg-gray-100 disabled:placeholder-gray-400 invalid:ring-red-400 focus:invalid:outline-none" />
</div>
<div class="flex flex-col items-end">
<TextBoxBase
@ref=@SignInPasswordTextBox
@[email protected]
Placeholder="What's the secret word ?"
CssClass="w-full py-3 px-6 ring-1 ring-gray-300 rounded-xl placeholder-gray-600 bg-transparent transition disabled:ring-gray-200 disabled:bg-gray-100 disabled:placeholder-gray-400 invalid:ring-red-400 focus:invalid:outline-none" />
<a href="/forgotten/password" type="reset" class="w-max p-3 -mr-3">
<span class="text-sm tracking-wide text-blue-600">Forgot password ?</span>
</a>
</div>
<div>
<ButtonBase
@ref=@SubmitButton
OnClick=@SignInAsync
Label="Login"
CssClass="w-full px-6 py-3 rounded-xl bg-sky-500 transition hover:bg-sky-600 focus:bg-sky-600 active:bg-sky-800" />
<SpinnerBase @ref=@Spinner />
</div>
</div>
下面是我的代码,一个 fluenteditform 表单。提交后,系统提示我填写了字段,但仍然需要填写。我的代码有什么问题?
@page "/movieform"
@using Assignment10.Entities
@using System.ComponentModel.DataAnnotations
<h3>MovieForm</h3>
<FluentCard>
<FluentEditForm FormName="MovieForm" Model="@movie">
<DataAnnotationsValidator />
<FluentValidationSummary />
<FluentGrid>
<FluentGridItem xs="12">
<FluentTextField Name="MovieNameField" Id="movieNameField" @bind-Value="movie.MovieName" Label="Name: " Required/>
<ValidationMessage For="@(() => movie.MovieName)" />
</FluentGridItem>
<FluentGridItem xs="12">
<FluentTextField Name="MoviePublisherField" Id="moviePublisherField" @bind-Value="movie.Publisher" Label="Publisher: " Required/>
<ValidationMessage For="@(() => movie.Publisher)" />
</FluentGridItem>
<FluentGridItem xs="12" >
<FluentTextField Name="MovieDescriptionField" Id="movieDescriptionField" @bind-Value="movie.MovieDescription" Label="Description: " Required/>
<ValidationMessage For="@(() => movie.MovieDescription)" />
</FluentGridItem>
<FluentGridItem xs="12" >
<FluentButton Type="ButtonType.Submit" Appearance="Appearance.Accent">Submit</FluentButton>
</FluentGridItem>
</FluentGrid>
</FluentEditForm>
</FluentCard>
@code {
private Movie movie = new Movie();
}
我想要使用 Blazor Bootstrap 的 SideBar。NewLayout.razor:
@inherits LayoutComponentBase
<div class="bb-page">
<Sidebar2 Href="/"
IconName="IconName.BootstrapFill"
Title="Blazor Bootstrap"
BadgeText="v2.1.0"
DataProvider="Sidebar2DataProvider" />
<main>
<div class="bb-top-row px-4 d-flex justify-content-end">
<a href="https://docs.microsoft.com/aspnet/" target="_blank">About</a>
</div>
<article class="content px-4" style="position: relative;">
<div class="py-2">
@Body
</div>
</article>
</main>
</div>
<style>
.bb-page {
display: flex;
width: 100%;
height: 100vh;
}
main {
flex: 1;
overflow: auto;
min-width: 0;
}
</style>
@code {
IEnumerable<NavItem>? navItems;
private async Task<Sidebar2DataProviderResult> Sidebar2DataProvider(Sidebar2DataProviderRequest request)
{
if (navItems is null)
navItems = GetNavItems();
return await Task.FromResult(request.ApplyTo(navItems));
}
private IEnumerable<NavItem> GetNavItems()
{
navItems = new List<NavItem>
{
new NavItem { Id = "1", Href = "/getting-started", IconName = IconName.HouseDoorFill, Text = "Getting Started"},
new NavItem { Id = "2", IconName = IconName.LayoutSidebarInset, Text = "Content" },
new NavItem { Id = "3", Href = "/icons", IconName = IconName.PersonSquare, Text = "Icons", ParentId="2"},
new NavItem { Id = "4", IconName = IconName.ExclamationTriangleFill, Text = "Components" },
new NavItem { Id = "5", Href = "/alerts", IconName = IconName.CheckCircleFill, Text = "Alerts", ParentId="4"},
new NavItem { Id = "6", Href = "/breadcrumb", IconName = IconName.SegmentedNav, Text = "Breadcrumb", ParentId="4"},
new NavItem { Id = "7", IconName = IconName.ListNested, Text = "Sidebar 2", ParentId="4"},
new NavItem { Id = "701", Href = "/sidebar2", IconName = IconName.Dash, Text = "How to use", ParentId="7"},
new NavItem { Id = "702", Href = "/sidebar2-examples", IconName = IconName.Dash, Text = "Examples", ParentId="7"},
new NavItem { Id = "8", IconName = IconName.WindowPlus, Text = "Forms" },
new NavItem { Id = "9", Href = "/autocomplete", IconName = IconName.InputCursorText, Text = "Auto Complete", ParentId="8"},
new NavItem { Id = "10", Href = "/currency-input", IconName = IconName.CurrencyDollar, Text = "Currency Input", ParentId="8"},
new NavItem { Id = "11", Href = "/number-input", IconName = IconName.InputCursor, Text = "Number Input", ParentId="8"},
new NavItem { Id = "12", Href = "/switch", IconName = IconName.ToggleOn, Text = "Switch", ParentId="8"},
};
return navItems;
}
}
我想将它用作客户端页面上的新布局。但它一直显示 3 点加载内容。( https://isstatic.askoverflow.dev/Jp3jQFK2.png )。有一个关于它的问题链接,但服务器项目中的 App.razor 对我来说不起作用。
我想将其用作客户端页面上的新布局。我发现此视频链接2最接近我想要的内容,但它在服务器端运行页面。
为了创建“@layout NewLayout”,布局必须在客户端,但即便如此,我也无法写入@rendermode InteractiveWebAssembly
布局。出现以下错误:
“InvalidOperationException:无法将参数‘Body’传递给渲染模式为‘InteractiveWebAssemblyRenderMode’的组件‘NewLayout’。这是因为该参数属于委托类型‘Microsoft.AspNetCore.Components.RenderFragment’,它是任意代码,无法序列化。”
我可以将焦点设置到FluentTextField上:
使用@ref:@ref=myFluentTextField
将其声明为 FluentTextField:FluentTextField?nombreFluentTextField;
设置焦点:
protected override void OnAfterRender(bool firstRender) { nombreFluentTextField?.FocusAsync(); }
如果我尝试使用FluentDatePicker执行相同操作,我会在控制台中收到此错误:
ElementReference 尚未正确配置。
所以,问题是:如何将焦点从代码设置到FluentDatePicker?
非常感谢,再见……
链接到 GitHub 以快速访问最小可重现示例(下面也提供了代码): https: //github.com/thecodeiackiller/cascadingSelectListProblem
注意:对于那些不熟悉健身领域的人来说,在给定的锻炼中,您通常有一种锻炼类型(腿部锻炼、上身锻炼等),并且在该锻炼中,您有运动类型(主要/较重的运动、次要运动和辅助运动(锻炼小肌肉)。
预期按时间顺序排列的用户流量:
问题:第二行的练习名称列表没有更新。练习名称列表与第一个练习相同,尽管练习类型不同,这应该会改变显示的练习。
我当前实现的AddWorkout.razor组件:
@using stateManagementMinimumReproducibleExample.Repositories
@using stateManagementMinimumReproducibleExample.Models
@page "/addworkout"
@rendermode InteractiveServer
@inject UserExerciseRepository userExerciseRepository
<EditForm Model="userExercise">
<label for="workoutType"> Workout Type: </label>
<InputSelect id="workoutType" @bind-Value="userExercise.WorkoutType" @bind-Value:after="GetExercisesByWorkoutType">
@foreach (var type in Enum.GetValues(typeof(WorkoutType)))
{
<option value="@type">@type</option>
}
</InputSelect>
@for (int i = 0; i < numberOfExercisesInWorkout; i++)
{
var j = i;
if (j >= exerciseListForSelectedDay.Count)
{
exerciseListForSelectedDay.Add(new UserExercise());
}
<div>
<label for="exerciseType"> Exercise Type: </label>
<InputSelect id="exerciseType" @bind-Value="exerciseListForSelectedDay[j].ExerciseType" @bind-Value:after="GetExercisesByExerciseType">
@foreach (var type in Enum.GetValues(typeof(ExerciseType)))
{
<option value="@type">@type</option>
}
</InputSelect>
<label for="exerciseName"> Exercise: </label>
<InputSelect id="exerciseName" @bind-Value="exerciseListForSelectedDay[j].ExerciseId">
@foreach (var exercise in listOfExerciseByExerciseType)
{
<option value="@exercise.Id">@exercise.Name</option>
}
</InputSelect>
</div>
}
</EditForm>
@code {
private int numberOfExercisesInWorkout = 2;
private UserExercise userExercise = new();
private List<UserExercise> exerciseListForSelectedDay = new();
public List<Exercise> listOfExercisesByWorkoutType = new();
public List<Exercise> listOfExerciseByExerciseType = new();
public async Task GetExercisesByWorkoutType()
{
listOfExercisesByWorkoutType = await userExerciseRepository.GetExercisesBasedOnWorkoutType(userExercise.WorkoutType);
StateHasChanged();
}
public void GetExercisesByExerciseType()
{
listOfExerciseByExerciseType = userExerciseRepository.GetExercisesFromWorkoutListBasedOnExerciseType(listOfExercisesByWorkoutType, userExercise.ExerciseType);;
}
}
我考虑过创建一个字典来存储锻炼中每项练习的练习列表的可能性。此外,我还考虑将 List 作为属性存储在我的 UserExercise 类中,然后将过滤后的练习列表添加到该属性中。我不确定我应该走哪条路,或者是否存在任何潜在的特定于 Blazor 的状态管理替代方案。
上面的代码应该能给你足够的信息来诊断问题。如果你需要直观的了解,以下是在分叉和克隆 GitHub 存储库后快速重现问题的步骤:
此时,您将看到,由于选择了与第一行不同的 ExerciseType,因此第二行的筛选列表尚未更新。我如何才能让第二行(及以后)的适当练习列表出现?谢谢。