Blazor:在使用 @bind 时如何在 <select> 中使用 onchange 事件?

Posted

技术标签:

【中文标题】Blazor:在使用 @bind 时如何在 <select> 中使用 onchange 事件?【英文标题】:Blazor: How to use the onchange event in <select> when using @bind also? 【发布时间】:2020-01-27 06:30:46 【问题描述】:

&lt;select&gt; 中进行选择后,我需要能够运行函数。问题是我也绑定了@bind,当我尝试使用@onchange 时出现错误,指出它已被@bind 使用。我尝试使用@onselectionchange,但这什么也没做(不运行该功能)。我可能会忘记@bind,而只是将@onchange 分配给一个函数,但我不确定如何将选定的值传递给函数。

我有以下代码:

<select @bind="@SelectedCustID" @ @onchange="@CustChanged" class="form-control">
    @foreach (KeyGuidPair i in CustList)
    
        <option value="@i.Value">@i.Text</option>
    
</select>

谢谢。

【问题讨论】:

只是附注:您可以使用@bind=SelectedCustID 代替@bind="@SelectedCustID"。它更干净:) 一个字符@ 好像是多余的。 见***.com/questions/58452319/… 【参考方案1】:
<select @bind="MyProperty">
<option>Your Option<option>
</select>

@code  
    private string myVar;

    public string MyProperty
    
        get  return myVar; 
        set
        
            myVar = value;
            SomeMethod();
        
    

    private void SomeMethod()
    
        //Do something
    

【讨论】:

这可行,但如果您需要进行一些异步调用,例如数据库更新,则会出现问题...... @Alexandre,我认为您可以使用 .Wait() 将异步调用转换为同步调用。见here。 应该选择不输入,因为用户要求选择代码。【参考方案2】:

@bind 本质上等同于同时拥有value@onchange,例如:

<input @bind="CurrentValue" />

相当于:

<input value="@CurrentValue" @onchange="@((ChangeEventArgs e) => CurrentValue = e.Value.ToString())" />

由于您已经定义了@onchange,所以不要同时添加@bind,只需添加value 以防止冲突:

<select value="@SelectedCustID" @onchange="@CustChanged" class="form-control">
    @foreach (KeyGuidPair i in CustList)
    
        <option value="@i.Value">@i.Text</option>
    
</select>

来源:https://docs.microsoft.com/en-us/aspnet/core/blazor/components/data-binding?view=aspnetcore-3.1

【讨论】:

只是提到你的解释,你说“相当于”帮助我弄清楚如何在 blazor select 的 onchange 事件上传递多个参数。谢谢。【参考方案3】:

这似乎是一个普遍的困惑。首先你不能使用@onchange,因为它会被@bind在内部使用。您应该能够从 CustChanged 属性的设置器中访问选定的值。根据您尝试对 CustChanged 执行的操作,您甚至可能不需要手动检查此值何时更新。例如,如果您的意图是在您的 UI 中直接或间接使用 CustChanged(在 Linq 或其他东西中),则当您的 &lt;select&gt; 更改时,UI 将自动更新为 CustChanged 值。因此,对于大多数用例,我认为不需要检查它何时更新。

要使用@onchange,您可以将其绑定到类似这样的函数:

public void OnUpdated(ChangeEventArgs e)

    var selected = e.Value;

【讨论】:

这是对所提问题的正确答案。 令人讨厌的是,这似乎实际上是选择了选项文本,而不是选项值【参考方案4】:

您可以完全避免使用@bind(如果您使用的是foreach):

<select @onchange=@(handleChange)>
    @foreach (var option in _options)
        <option value=@option.Id selected=@(SelectedId == option.Id)>@option.Name</option>
    
</select>

@code 
    public record Person(int Id, string Name);
    public int SelectedId  get; set; 
    public List<Person> _options = new List<Person>() 
        new Person(1,"A"),
        new Person(2,"B"),
        new Person(3,"C")
    ;

    public void handleChange(ChangeEventArgs args) 
        Console.WriteLine(args.Value);
        SelectedId = Int32.Parse(args.Value.ToString());
    



一些肮脏的细节:在尝试将 F# 与服务器端 Blazor 一起使用时,我遇到了一些奇怪的行为。简而言之,将选项的 List 设置为实体框架查询的结果(映射到记录列表)不会正确地 @bind,而是使用 C# 类而不是 F# 记录的虚拟选项列表 确实工作。但这不是因为它是记录,因为如果我将列表设置为 EF 查询,然后立即将其设置为虚拟记录列表,它仍然没有正确地 @bind - 但它 确实 如果我注释掉 EF 行,就可以工作。

【讨论】:

true 或 false 对所选属性无效***.com/questions/1033944/… @Alexandre True。但是,Blazor 将 selected=true/false 转换为有效的 html。 i.imgur.com/QEDQceP.png 同样适用于其他属性,例如 disabled: ***.com/questions/55002514/… 也 blazor-university.com/components/code-generated-html-attributes 嗨 DharmaTurlte 能否请您详细说明@onchange=@(x => ...)。 lambda 表达式有什么用途。我必须在那里写什么代码(方法调用?如何?)。谢谢 @nogood 我填写了 lambda。如果您仍然感到困惑,请 LMK。【参考方案5】:

只需添加@bind-value 和@bind-vale:event 和@onchnage,如下所示。注意小写字母。这对我有用,没有任何问题。

<select @bind-value="variablenametokeepselectedvalue" @onchange="yourmethodname" @bind-value:event="oninput">
 <option value="1">Test</option>
</select>

【讨论】:

【参考方案6】:

请检查此示例。它正在使用 @bind 但在设置值时会触发 @onchange 事件

<div class="form-group">
    <label for="client">Client Name</label>
    <select id="client" @bind="CheckSelected" class="form-control">
       <option value="selected1">selected1</option>
       <option value="selected2">selected2</option>
    </select>
</div>
@code 

    私有字符串 selectedItem get;放;

    私有字符串 CheckSelected
    
        得到
        
            返回选中项;
        
        放
        
            ChangeEventArgs selectedEventArgs = new ChangeEventArgs();
            selectedEventArgs.Value = 值;
            OnChangeSelected(selectedEventArgs);
        
    

    私人无效 OnChangeSelected(ChangeEventArgs e)
    
        if (e.Value.ToString() != string.Empty)
        
            selectedItem = e.Value.ToString();
        
    


【讨论】:

值得注意的是,此解决方案适用于 blazor EditForm (***.com/questions/61756167/…),因为 InputSelect 无法通过以下方式正确绑定事件:&lt;InputSelect Id="Source" @bind-Value="@model.Source" Class="form-control" @onchange="HandleSourceOptionChanged"&gt;【参考方案7】:

如果可能,我的建议是在表单元素周围使用 EditForm 包装器。然后,您可以在一个地方检测到任何表单元素的变化。例如,这适用于一堆搜索过滤器。任何过滤器的任何更改都应触发对数据的另一次查询,等等。

如何在表单更改时触发事件的示例在这里:

blazor editform change events

【讨论】:

【参考方案8】:

<div class="form-group">
    <label for="client">Client Name</label>
    <select class="form-control" @onchange="@((e) =>  myVar = e.Value.ToString(); MyMethod(); )">
       <option value="val1">val1</option>
       <option value="val2">val2</option>
    </select>
</div>

这就是我在@onchange 事件中调用方法时设置属性的方式。

-Blazor 服务器 -Dotnet Core 3.1

【讨论】:

【参考方案9】:

根据Microsoft's documentation,这是他们处理此问题的首选方式:

<InputText Value="@NewPaymentAmount" class="mdl-textfield__input"
           ValueExpression="() => NewPaymentAmount"
           ValueChanged="(string value) => ValidateAmount(value)" />



private void ValidateAmount(string amount)

    NewPaymentAmount = amount;
    
    // Do validation or whatever

或者async方式:

<InputText Value="@NewPaymentAmount" class="mdl-textfield__input"
           ValueExpression="() => NewPaymentAmount"
           ValueChanged="async (string value) => await ValidateAmountAsync(value)" />



private async Task ValidateAmountAsync(string amount)

    NewPaymentAmount = amount;
    
    // Do validation or whatever

【讨论】:

以上是关于Blazor:在使用 @bind 时如何在 <select> 中使用 onchange 事件?的主要内容,如果未能解决你的问题,请参考以下文章

Blazor数据绑定

使用参数在 blazor 中重定向

在 Razor 页面中使用 Blazor @bind

如何限制 Blazor 服务器端请求大小

组件内的 Blazor 双向绑定文本区域

Blazor MudSelect @bind-SelectedValues 到 id 和 value