英文:
Blazor Func Property to return calculated value
问题
在之前的问题的基础上,我在尝试让它工作时遇到了困难。
首先来看确实工作的部分,我在一个类上有一个属性,它会在按钮点击时发生。
public Func<Task> SelectAction { get; set; }
Razor 部分如下(这一切都是为了消除昂贵且减慢页面速度的 lambda 表达式)。
<div class="cv-selectable" @onclick="row.SelectAction">
SelectAction
设置如下:
newClaim.SelectAction = () => SwapClaimSelectedState(newClaim);
SwapClaimSelectedState
实际上会更改内部属性的值。这很有效。以下是完整的代码(问题随后提出)。
Razor 页面:
@foreach (var row in VisibleDestinations)
{
if (row.RowType == VirtualCopyRowTypes.Claim)
{
<div class="cv-row cv-claim">
<div>
<button type="button" class="btn btn-link" @onclick="row.ExpandAction">
<Icon Name="@row.ExpandStateIcon" height="15" />
</button>
<div class="cv-selectable" @onclick="row.SelectAction">
<button type="button" class="btn btn-link">
<Icon Name="@row.DetermineClaimsIconState" height="15" />
</button>
<span>@row.ClaimDisplay</span>
</div>
</div>
</div>
}
}
VisibleDestinations
中的 "row" 属性:
[JsonIgnore]
public Func<Task> SelectAction { get; set; }
[JsonIgnore]
public Func<Task> ExpandAction { get; set; }
[JsonIgnore]
public Func<Task> DetermineClaimsIconState { get; set; }
设置 VisibleDestinations
的循环:
foreach (var claim in AllPerformanceClaimsWithVisgrades)
{
var newClaim = new VirtualCopyRow
{
PerformanceClaimId = claim.PerformanceClaimId,
RowType = VirtualCopyRowTypes.Claim,
IsVisible = true,
ClaimDisplay = $"{claim.Issuer} {claim.Name} {claim.Version}",
};
newClaim.ExpandAction = () => SwapCollapsedState(newClaim);
newClaim.SelectAction = () => SwapClaimSelectedState(newClaim);
newClaim.DetermineClaimsIconState = () => ClaimSelectedStateIcon(newClaim);
// ...
}
我想在 Razor 语法中调用的方法基本上会根据子对象的选择状态返回4种可能的图标状态之一。思考未选择、部分选择和全部选择:
public async Task ClaimSelectedStateIcon(VirtualCopyRow row)
{
var result = IconNames.Blank;
var totalChildVisgrades = Destinations
.Count(x =>
x.PerformanceClaimId == row.PerformanceClaimId &&
x.RowType == VirtualCopyRowTypes.Visgrade
);
var totalSelectedVisgrades = Destinations
.Count(x =>
x.PerformanceClaimId == row.PerformanceClaimId &&
x.RowType == VirtualCopyRowTypes.Visgrade &&
x.IsSelected == true
);
if (totalChildVisgrades == 0)
result = IconNames.Blank; // 此索赔上没有 Visgrades
else if (totalSelectedVisgrades == 0)
result = IconNames.UnselectAll; // 此索赔上至少有一个 Visgrade,但没有选中任何一个
else if (totalChildVisgrades == totalSelectedVisgrades)
result = IconNames.SelectAll; // 此索赔上至少有一个 Visgrade,且全部都选中了
else
result = IconNames.SomeSelected; // 此索赔上至少有两个 Visgrade,至少一个被选中但不是全部都选中了
return result;
}
问题
我尝试了多种方式来定义 DetermineClaimsIconState
属性,其中有一个 in
和/或 TValue
的 IconNames
,但无论是在代码还是 Razor 中都会出现问题。
如果其他类型可以工作,我不需要这是一个 Func
。主要要求是代码后台需要类似于以下内容:
newClaim.DetermineClaimsIconState = () => ClaimSelectedStateIcon(newClaim);
在 Razor 代码中不是 Lambda,所以它应该类似于:
<Icon Name="@row.DetermineClaimsIconState" height="15" />
更新
在尝试实现 @MrC-aka-shaun-curtis 的更新后,C# 部分是正确的,但 Razor 部分出现了以下错误。
英文:
Expanding on a prior question, I am having difficulty getting it to work.
To start with the part that Does work, I have a property on a class that happens upon click of a button.
public Func<Task> SelectAction { get; set; }
The razor portion looks like the following (this is all in an effort to remove lambdas which are expensive and slow the page down.)
<div class="cv-selectable" @onclick="row.SelectAction">
The SelectAction
is setup like the following:
newClaim.SelectAction = () => SwapClaimSelectedState(newClaim);
The SwapClaimSelectedState
essentially changes an internal properties value. This works great. Here is the full code (question to follow.)
The razor page:
@foreach (var row in VisibleDestinations)
{
if (row.RowType == VirtualCopyRowTypes.Claim)
{
<div class="cv-row cv-claim">
<div>
<button type="button" class="btn btn-link" @onclick="row.ExpandAction">
<Icon Name="@row.ExpandStateIcon" height="15" />
</button>
<div class="cv-selectable" @onclick="row.SelectAction">
<button type="button" class="btn btn-link">
<Icon Name="@row.DetermineClaimsIconState" height="15" />
</button>
<span>@row.ClaimDisplay</span>
</div>
</div>
</div>
}
}
The VisibleDestinations
"row" properties in question:
[JsonIgnore]
public Func<Task> SelectAction { get; set; }
[JsonIgnore]
public Func<Task> ExpandAction { get; set; }
[JsonIgnore]
public Func<Task> DetermineClaimsIconState { get; set; }
The loop to setup the VisibleDestinations
:
foreach (var claim in AllPerformanceClaimsWithVisgrades)
{
var newClaim = new VirtualCopyRow
{
PerformanceClaimId = claim.PerformanceClaimId,
RowType = VirtualCopyRowTypes.Claim,
IsVisible = true,
ClaimDisplay = $"{claim.Issuer} {claim.Name} {claim.Version}",
};
newClaim.ExpandAction = () => SwapCollapsedState(newClaim);
newClaim.SelectAction = () => SwapClaimSelectedState(newClaim);
newClaim.DetermineClaimsIconState = () => ClaimSelectedStateIcon(newClaim);
...
}
The method that I want to call within the razor syntax essentially returns 1 of 4 possible icon states based on child object selection states. Think none-selected, some-selected and all-selected:
public async Task ClaimSelectedStateIcon(VirtualCopyRow row)
{
var result = IconNames.Blank;
var totalChildVisgrades = Destinations
.Count(x =>
x.PerformanceClaimId == row.PerformanceClaimId &&
x.RowType == VirtualCopyRowTypes.Visgrade
);
var totalSelectedVisgrades = Destinations
.Count(x =>
x.PerformanceClaimId == row.PerformanceClaimId &&
x.RowType == VirtualCopyRowTypes.Visgrade &&
x.IsSelected == true
);
if (totalChildVisgrades == 0)
result = IconNames.Blank; // There are no Visgrades on this Claim
else if (totalSelectedVisgrades == 0)
result = IconNames.UnselectAll; // There is at least one Visgrade on the Claim and None are selected
else if (totalChildVisgrades == totalSelectedVisgrades)
result = IconNames.SelectAll; // There is at least one Visgrade on the Claim and they are All selected
else
result = IconNames.SomeSelected; // There is at least two Visgrades on the Claim and at least one but not All are selected
return result;
}
Question
I have tried multiple permutations of how to define the DetermineClaimsIconState
property where I have an in
and/or TValue
of IconNames
and there is always some issue either in code or razor.
I do NOT need this to be a Func
if some other type will work. The main requirement is that the code-behind needs to be something similar to:
newClaim.DetermineClaimsIconState = () => ClaimSelectedStateIcon(newClaim);
Where I pass the newClaim
object to the ClaimSelectiedStateIcon
method.
AND that the razor code is NOT a lambda so it should look similar to:
<Icon Name="@row.DetermineClaimsIconState" height="15" />
UPDATE
After attempting to implement @MrC-aka-shaun-curtis updates, the c# is good but the razor gives the following error.
答案1
得分: 1
看着你的方法 ClaimSelectedStateIcon
:
- 返回类型是
Task
,但你尝试返回一个IconValues
对象 [我假设是一个枚举?]。 - 我没有看到任何异步方法调用,所以我假设你正在收到关于这方面的警告。
它应该像这样:
public Task<IconNames> ClaimSelectedStateIcon(VirtualCopyRow row)
{
var result = IconNames.Blank;
//....
return Task.FromResult(result);
}
而你的委托声明:
public Func<Task<IconNames>> DetermineClaimsIconState { get; set; }
英文:
Looking at your method ClaimSelectedStateIcon
:
- The return type is
Task
, but you try to return anIconValues
object [I assume an enum?]. - I see no async methods called so I assume you're getting warnings about that.
It should look like:
public Task<IconNames> ClaimSelectedStateIcon(VirtualCopyRow row)
{
var result = IconNames.Blank;
//....
return Task.FromResult(result);
}
And your delegate declared:
public Func<Task<IconNames>> DetermineClaimsIconState { get; set; }
答案2
得分: 0
感谢 @mrc-aka-shaun-curtis 的协助。最终产品是:
public Func<VirtualizedRow, IconNames> GetBulkCopyIconState { get; set; }
public IconNames BulkIconStateForRow
{
get
{
var result = IconNames.Blank;
if (GetBulkCopyIconState is not null)
result = GetBulkCopyIconState.Invoke(this);
return result;
}
}
当创建不同行时,它们都设置如下:
visgradeRow.GetBulkCopyIconState = (e) => DetermineBulkCopyIconState(visgradeRow);
进行实际计算以确定显示哪个图标:
public IconNames DetermineBulkCopyIconState(VirtualizedRow row)
{
... 魔法酱
return result;
}
在 Razor 页面/组件上使用:
<button type="button" class="btn btn-sm btn-link p-0 bulk-copy" @onclick="cell.SecondaryAction">
<Icon Name="@row.BulkIconStateForRow" height="12" class="@row.BulkIconStateForRow" />
</button>
英文:
Thanks to @mrc-aka-shaun-curtis for assistance. The final product is:
public Func<VirtualizedRow, IconNames> GetBulkCopyIconState { get; set; }
public IconNames BulkIconStateForRow
{
get
{
var result = IconNames.Blank;
if (GetBulkCopyIconState is not null)
result = GetBulkCopyIconState.Invoke(this);
return result;
}
}
When creating differet rows, they all are setup like the following:
visgradeRow.GetBulkCopyIconState = (e) => DetermineBulkCopyIconState(visgradeRow);
Do the actual calculation for determining which icon to show:
public IconNames DetermineBulkCopyIconState(VirtualizedRow row)
{
... Magic sauce
return result;
}
Using it on the razor page/component:
<button type="button" class="btn btn-sm btn-link p-0 bulk-copy" @onclick="cell.SecondaryAction">
<Icon Name="@row.BulkIconStateForRow" height="12" class="@row.BulkIconStateForRow" />
</button>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论