我正在学习Blazor和ASP.NET,并且过去6个月一直在学习C#。
我制作了一个简单的模板化组件:
@typeparam GenericType
<ul>
@foreach (GenericType item in Items)
{
<li @onclick="(x)=> ItemClicked(item)">FragmentToRender(item)</li>
}
</ul>
@code {
[Parameter] public RenderFragment<GenericType> FragmentToRender { get; set; }
[Parameter] public IReadOnlyList<GenericType> Items { get; set; }
public void ItemClicked(GenericType item)
{
//To figure out...
}
}
我正在页面组件中使用它:
<TestComponent GenericType="Thing" Items="ListOfThings">
<FragmentToRender>
<p>@context.Field</p>
</FragmentToRender>
</TestComponent>
@code
{
private List<Thing> ListOfThings =
new List<Thing> {
new Thing("Test"),
new Thing("Test2")
};
public class Thing
{
public readonly string Field;
public Thing(string field) => Field = field;
}
}
当触发组件中li元素的OnClick事件时,如何将项目的特定实例传递回页面组件(即,不同的组件可以对被单击的项目执行某些操作,例如将其数据上传到某处)?
非常感谢
答案 0 :(得分:2)
您应该使用EventCallback
传递数据。
@typeparam GenericType
<ul>
@foreach (GenericType item in Items)
{
<li @onclick="(x)=> ItemClicked(item)">FragmentToRender(item)</li>
}
</ul>
@code {
[Parameter] public RenderFragment<GenericType> FragmentToRender { get; set; }
[Parameter] public IReadOnlyList<GenericType> Items { get; set; }
// Added EventCallback parameter
[Parameter] public EventCallback<GenericType> OnClick { get; set; }
public void ItemClicked(GenericType item)
{
// Checking if EventCallback is set
if(OnClick.HasDelegate)
{
// Calling EventCallback
OnClick.InvokeAsync(item);
}
}
}
然后将参数OnClick
传递给该组件以获取商品
@* Passing the OnClick parameter *@
<TestComponent GenericType="Thing" Items="ListOfThings" OnClick="@HandleClick">
<FragmentToRender>
<p>@context.Field</p>
</FragmentToRender>
</TestComponent>
@code
{
private void HandleClick(Thing item)
{
// Do what you want with the item
}
private List<Thing> ListOfThings =
new List<Thing> {
new Thing("Test"),
new Thing("Test2")
};
public class Thing
{
public readonly string Field;
public Thing(string field) => Field = field;
}
}
答案 1 :(得分:1)
注意:我在您的代码示例中做了一些改动... 注意事项:
在FragmentToRender(item)之前添加一个@符号。它指示编译器将FragmentToRender(item)视为可执行代码。否则,它将用作li元素的内容。
在li元素的第二个版本中,我们将事件调用放回
lambda表达式的主体。如果您使用此版本,请注释
ItemClicked方法。
@typeparam GenericType
<ul>
@foreach (GenericType item in Items)
{
<li @onclick="() => ItemClicked(item)">@FragmentToRender(item)</li>
@*<li @onclick="@(() => SelectedItem.InvokeAsync(item))">@FragmentToRender(item)</li>*@
}
</ul>
@code {
[Parameter] public RenderFragment<GenericType> FragmentToRender { get; set; }
[Parameter] public IReadOnlyList<GenericType> Items { get; set; }
// Define an event call back property.
[Parameter] public EventCallback<GenericType> SelectedItem { get; set; }
public async Task ItemClicked(GenericType item)
{
// Check if the event call back property contains a delegate. It's
// important to understand that the EventCallback type is not a true
// delegate. It is actually a struct that may contain a delegate
if(SelectedItem.HasDelegate)
{
await SelectedItem.InvokeAsync(item);
}
}
}
<TemplatedComponent GenericType="Thing" Items="ListOfThings"
SelectedItem="SelectedItem">
<FragmentToRender>
<p>@context.Field</p>
</FragmentToRender>
</TemplatedComponent>
@code
{
// Define a method that will be called by the event call back 'delegate'. It
// receives a single parameter from the calling delegate.
private async Task SelectedItem(Thing item)
{
Console.WriteLine(item.Field);
await Task.CompletedTask;
}
private List<Thing> ListOfThings =
new List<Thing> {
new Thing("Test"),
new Thing("Test2")
};
public class Thing
{
public readonly string Field;
public Thing(string field) => Field = field;
}
}
@page "/"
<TestComponent/>
希望这对您有帮助...