【问题标题】:Blazor OnChange EventBlazor OnChange 事件
【发布时间】:2021-04-24 10:34:28
【问题描述】:

我想绑定到该值并在更改后触发 CalculateStandardDimensions 方法。我已经尝试了几种不同的语法组合,但我仍然缺少一些东西来完成这项工作。 离开输入不执行方法。

如何绑定值并在值发生变化时调用方法?

<input class="form-control form-control-sm" type="number" step="any" @bind-value:event="onchange=CalculateStandardDimensions()" @bind-value="Cyclone.CycloneSize" />

我在代码部分有这个。

    private void CalculateStandardDimensions()
    {
        // Do Stuff Here
    }

【问题讨论】:

    标签: c# html blazor


    【解决方案1】:

    这似乎是一项简单的任务,但您需要考虑一些事项。

    在 Blazor 中,从输入返回到模型的通道是通过事件处理的。如果您使用@bind- 语法,编译器会为您构建处理程序。因此,您不能(轻松)更新模型值并同时执行另一个处理程序。

    但是,有一些方便的方法可以实现您想要的。但它们也有缺点。根据您的具体情况,您需要决定什么是最好的。

    使用不同的事件

    @page "/DifferentEvents"
    
    <input class="form-control form-control-sm" type="number" step="any" 
           @bind-value:event="onchange" @oninput="CalculateStandardDimensions"  @bind-value="Cyclone.CycloneSize" />
    
    @code
    {
        public class Cyclon
        {
            public Int32 CycloneSize { get; set; } = 10;
        }
    
        public Cyclon Cyclone = new Cyclon();
    
        private void CalculateStandardDimensions(ChangeEventArgs args)
        {
            // Do Stuff Here
        }
    
    }
    

    在这种情况下,当输入失去焦点(onchange)时,您的模型将更新,但每次输入更改时都会执行您的方法CalculateStandardDimensions。新值可通过ChangeEventArgs args 访问。

    缺点:潜在的不一致,因为模型不知道更新,但你用它来做其他事情。

    使用具有双向绑定的中介属性

    @page "/IntermediatePropertyWithBinding"
    
    <input class="form-control form-control-sm" type="number" step="any" @bind-value:event="onInput" @bind-value="Size" />
    
    @code
    {
        public class Cyclon
        {
            public Int32 CycloneSize { get; set; } = 10;
        }
    
        public Cyclon Cyclone = new Cyclon();
    
        private Int32 _size;
    
        public Int32 Size
        {
            get => _size;
            set
            {
                _size = value;
                CalculateStandardDimensions();
                Cyclone.CycloneSize = value;
            }
        }
    
        private void CalculateStandardDimensions()
        {
            // Do Stuff Here
        }
    }
    
    

    通过使用属性Size 引入字段_size,您可以绑定Size 的setter 将调用CalculateStandardDimensions()。根据绑定onInputonChange的事件,可以控制回写的时间。

    您可以完全控制绑定,并避免不一致。但是,您引入了一个新字段和属性。需要对您希望具有此类行为的每个属性执行此操作。

    使用没有绑定的中介属性

    @page "/IntermediatePropertyWithoutBinding"
    
    <input class="form-control form-control-sm" type="number" step="any" value="@_size" @oninput="ValueChanged" />
    
    @code
    {
        public class Cyclon
        {
            public Int32 CycloneSize { get; set; } = 10;
        }
    
        public Cyclon Cyclone = new Cyclon();
    
        private Int32 _size;
    
        private void ValueChanged(ChangeEventArgs args)
        {
            _size = Convert.ToInt32((String)args.Value);
            Cyclone.CycloneSize = _size;
            CalculateStandardDimensions();
        }
    
        private void CalculateStandardDimensions()
        {
            // Do Stuff Here
        }
    }
    

    我们摆脱了绑定和属性。输入字段的值是直接设置的。 (没有@bind-value)。在事件处理程序中,我们设置更新值、写回模型并执行CalculateStandardDimensions() 方法。

    我们失去了双向绑定的所有功能,但不再需要属性。

    EditContext OnFieldChanged 事件

    @page "/WithEditContext"
    @implements IDisposable
    
    <EditForm EditContext="_editContext">
        <InputNumber class="form-control form-control-sm" type="number" step="any" @bind-Value:event="onchange" @bind-Value="Cyclone.CycloneSize" />
    </EditForm>
    
    @code
    {
        public class Cyclon
        {
            public Int32 CycloneSize { get; set; } = 10;
        }
    
        private EditContext _editContext;
    
        public Cyclon Cyclone = new Cyclon();
    
        protected override void OnInitialized()
        {
            base.OnInitialized();
    
            _editContext = new EditContext(Cyclone);
            _editContext.OnFieldChanged += OnFormUpdated;
        }
    
        public void Dispose()
        {
            _editContext.OnFieldChanged -= OnFormUpdated;
        }
    
        private void OnFormUpdated(Object sender,  FieldChangedEventArgs args)
        {
            if(args.FieldIdentifier.FieldName == nameof(Cyclon.CycloneSize))
            {
                CalculateStandardDimensions();
            }
        }
    
        private void CalculateStandardDimensions()
        {
        }
    }
    

    EditContext 是在使用和带有Model 属性的 EditForm 时隐式创建的,它有一个在将值写回模型时触发的事件。我们通过显式创建 EditContext 并订阅事件来使用它。不要忘记稍后删除处理程序。这就是我们实施IDisposable 的原因。事件处理程序本身会检查该字段是否是我们所期望的并执行方法CalculateStandardDimensions()。需要将 HTML 输入元素替换为 InputNumber 才能使绑定生效。

    这种方法具有极大的灵活性,但也带来了更多的复杂性。但是,您可以将它与 InputTextInputSelect 等每个输入组件一起使用。

    【讨论】:

    • 我尝试了 EditContext 选项的代码,但是当值更改时事件没有触发。我从模板创建了一个新的 Blazor Server 应用程序,然后从上面添加了代码,但没有触发 OnFormUpdated。我正在更多地研究这个选项,因为我猜这是一个小问题。
    • 一个小副本和过去的错误将&lt;input ... 替换为&lt;InputNumber class="form-control form-control-sm" type="number" step="any" @bind-Value:event="onchange" @bind-Value="Cyclone.CycloneSize" /&gt; 我已经更新了代码并添加了一个小解释。
    • 非常感谢您的帮助。我刚刚弄清楚了这一点,然后回来发布我发现的内容。我将不得不阅读更多关于绑定以这种方式工作的原因。再次非常感谢!
    • 很棒的答案,非常感谢。
    猜你喜欢
    • 2020-05-16
    • 1970-01-01
    • 1970-01-01
    • 2020-12-18
    • 1970-01-01
    • 2020-10-08
    • 1970-01-01
    • 2018-10-01
    • 1970-01-01
    相关资源
    最近更新 更多