You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Blazor Wasm表单条件验证实现咨询

Blazor Wasm表单条件验证实现咨询

嗨,我完全懂你现在的处境——原来的表单有个必填的下拉框,现在加了新功能,用户可以选要么用下拉框,要么点按钮输入自定义值,这时候得做二选一的条件验证对吧?这种场景在Blazor里其实有几种很实用的实现方式,我给你一步步拆解下:


一、先理清核心需求

本质上是要实现互斥的条件验证:

  • 如果用户选择用下拉框,那下拉框必须选值,自定义输入区域可以忽略
  • 如果用户切换到自定义输入,那自定义的字段必须填全,下拉框可以不用选

二、实现方式一:自定义验证属性(适合模型驱动的验证)

你可以给表单模型加一个自定义的验证特性,让它根据用户的选择动态判断哪部分字段需要验证。

1. 先定义表单模型

public class MyFormModel
{
    // 原下拉框绑定属性
    public int? SelectedDropdownId { get; set; }

    // 自定义输入的字段
    public string CustomField1 { get; set; }
    public string CustomField2 { get; set; }

    // 标记用户是否选择自定义输入
    public bool IsUsingCustomInput { get; set; }
}

2. 创建自定义验证属性

public class EitherRequiredAttribute : ValidationAttribute
{
    private readonly string _primaryProperty;
    private readonly string[] _secondaryProperties;

    public EitherRequiredAttribute(string primaryProperty, params string[] secondaryProperties)
    {
        _primaryProperty = primaryProperty;
        _secondaryProperties = secondaryProperties;
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        var model = validationContext.ObjectInstance as MyFormModel;
        if (model == null) return ValidationResult.Success;

        if (!model.IsUsingCustomInput)
        {
            // 验证下拉框是否选中
            var primaryValue = validationContext.ObjectType.GetProperty(_primaryProperty)?.GetValue(model);
            if (primaryValue == null || (primaryValue is int id && id == 0))
            {
                return new ValidationResult("请选择下拉框选项", new[] { _primaryProperty });
            }
        }
        else
        {
            // 验证所有自定义字段是否填写
            foreach (var propName in _secondaryProperties)
            {
                var propValue = validationContext.ObjectType.GetProperty(propName)?.GetValue(model);
                if (propValue == null || string.IsNullOrWhiteSpace(propValue.ToString()))
                {
                    return new ValidationResult($"请填写{propName}", new[] { propName });
                }
            }
        }

        return ValidationResult.Success;
    }
}

3. 给模型添加验证标记

[EitherRequired(nameof(SelectedDropdownId), nameof(CustomField1), nameof(CustomField2))]
public class MyFormModel { /* ... 模型字段 ... */ }

三、实现方式二:用EditContext手动控制验证(更灵活)

如果不想用自定义属性,也可以直接在组件里通过EditContext订阅验证事件,手动编写条件验证逻辑。

1. 组件里的代码

<EditForm EditContext="@_editContext" OnValidSubmit="@HandleSubmit">
    <DataAnnotationsValidator />
    <ValidationSummary />

    <!-- 下拉框区域 -->
    @if (!Model.IsUsingCustomInput)
    {
        <div class="form-group">
            <label>选择预设选项:</label>
            <InputSelect @bind-Value="Model.SelectedDropdownId">
                <option value="">请选择</option>
                <option value="1">选项1</option>
                <option value="2">选项2</option>
            </InputSelect>
            <ValidationMessage For="@(() => Model.SelectedDropdownId)" />
        </div>
    }

    <!-- 切换按钮 -->
    <button type="button" @onclick="ToggleInputMode">
        @(Model.IsUsingCustomInput ? "切换为预设选择" : "切换为自定义输入")
    </button>

    <!-- 自定义输入区域 -->
    @if (Model.IsUsingCustomInput)
    {
        <div class="form-group">
            <label>自定义字段1:</label>
            <InputText @bind-Value="Model.CustomField1" />
            <ValidationMessage For="@(() => Model.CustomField1)" />
        </div>
        <div class="form-group">
            <label>自定义字段2:</label>
            <InputText @bind-Value="Model.CustomField2" />
            <ValidationMessage For="@(() => Model.CustomField2)" />
        </div>
    }

    <button type="submit">提交表单</button>
</EditForm>

@code {
    private MyFormModel Model { get; set; } = new MyFormModel();
    private EditContext _editContext;

    protected override void OnInitialized()
    {
        _editContext = new EditContext(Model);
        // 订阅验证请求事件
        _editContext.OnValidationRequested += ValidateConditionally;
        base.OnInitialized();
    }

    private void ToggleInputMode()
    {
        Model.IsUsingCustomInput = !Model.IsUsingCustomInput;
        // 切换后触发一次验证,更新提示
        _editContext.Validate();
    }

    private void ValidateConditionally(object sender, ValidationRequestedEventArgs e)
    {
        var messageStore = new ValidationMessageStore(_editContext);
        messageStore.Clear();

        if (!Model.IsUsingCustomInput)
        {
            if (!Model.SelectedDropdownId.HasValue)
            {
                messageStore.Add(() => Model.SelectedDropdownId, "请选择预设选项");
            }
        }
        else
        {
            if (string.IsNullOrWhiteSpace(Model.CustomField1))
            {
                messageStore.Add(() => Model.CustomField1, "自定义字段1不能为空");
            }
            if (string.IsNullOrWhiteSpace(Model.CustomField2))
            {
                messageStore.Add(() => Model.CustomField2, "自定义字段2不能为空");
            }
        }

        // 通知验证状态变化
        _editContext.NotifyValidationStateChanged();
    }

    private void HandleSubmit()
    {
        // 处理表单提交逻辑
        Console.WriteLine("表单验证通过,开始提交");
    }
}

四、小提示

  • 切换输入模式时,记得手动触发一次EditContext.Validate(),让用户及时看到验证提示
  • 如果自定义字段有更复杂的验证规则(比如格式、长度),可以给这些字段单独加数据注解,条件验证会和这些规则兼容

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.08 12:39:41