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

DotVVM Business Pack GridView:验证与表单编辑问题咨询

DotVVM GridView 内联验证与表单编辑方案

一、内联插入/编辑的验证方案(支持数据注解+自定义验证)

1. 数据注解验证的正确配置

你当前代码的验证目标绑定有误——内联编辑/插入时,验证应该针对当前编辑的单行实体,而非整个Bloods数据源集合。

修正要点:

  • 先在实体类(比如Blood)的属性上添加数据注解,例如给BloodProductID加必填验证:
    [Required(ErrorMessage = "产品不能为空")]
    public int BloodProductID { get; set; }
    
  • 确保需要验证的GridView列开启Validation.Enabled="true",并正确绑定Validator.Value(你已经在ComboBoxColumn做了这一步,若Comments等其他字段需要验证,也要对应配置)。
  • 保存按钮的Validation.Target要绑定到当前编辑的行({value: _this}),注意你的代码里该属性少了引号,修正后示例:
    <bp:Button Text="Save"
               Type="Success"
               Click="{command: _parent.SaveNewBlood()}"
               Visible="{value: _parent.IsBloodInserting}"
               Validation.Target="{value: _this}" />
    

2. 自定义验证的实现

如果需要业务规则类的自定义验证,有两种方式:

  • 命令内手动添加错误:在ViewModel的保存命令里编写逻辑,将错误加入ValidationErrors集合:
    public void SaveNewBlood()
    {
        var newBlood = Bloods.InsertRow;
        // 自定义规则:选择特定产品时备注不能为空
        if (newBlood.BloodProductID == 1 && string.IsNullOrWhiteSpace(newBlood.Comments))
        {
            ValidationErrors.Add(nameof(Bloods.InsertRow.Comments), "选择该产品时备注不能为空");
            return;
        }
        // 执行保存逻辑
        Bloods.FinishInsert();
    }
    
  • 自定义验证特性:用[CustomValidation]标记实体属性,实现ValidationAttribute子类来封装验证逻辑。

3. 错误显示优化

  • 你外层div设置的Validator.InvalidCssClass="has-error"会自动给验证失败的控件添加样式,配合Bootstrap就能显示错误状态。
  • 若要显示具体错误文本,可以在列内添加dot:ValidationMessage控件:
    <bp:GridViewComboBoxColumn Validation.Enabled="true" 
                               Validator.Value="{value: BloodProductID}" 
                               Value="{value: BloodProductID}" 
                               DataSource="{value: ProductList }" 
                               ItemValueBinding="{value: Value}" 
                               ItemTextBinding="{value: Text}" 
                               HeaderText="Product">
        <ItemTemplate>
            <dot:ComboBox ... />
            <dot:ValidationMessage For="{value: BloodProductID}" class="text-danger" />
        </ItemTemplate>
    </bp:GridViewComboBoxColumn>
    

二、实现类似DevExpress的表单/Popup编辑模式

DotVVM GridView没有内置PopupEditForm,但可以通过Popup控件+ViewModel绑定快速实现,步骤如下:

1. ViewModel添加绑定属性

public Blood SelectedBlood { get; set; }
public bool IsEditPopupOpen { get; set; }
public bool IsInsertPopupOpen { get; set; }

// 触发编辑弹窗
public void EditBlood(int rowId)
{
    SelectedBlood = Bloods.Rows.First(b => b.RowID == rowId);
    IsEditPopupOpen = true;
}

// 保存编辑内容
public void SaveEditedBlood()
{
    // 先验证
    if (!IsValid(nameof(SelectedBlood))) return;
    
    // 更新数据源
    Bloods.UpdateRow(SelectedBlood);
    IsEditPopupOpen = false;
}

// 触发插入弹窗
public void OpenInsertPopup()
{
    SelectedBlood = new Blood();
    IsInsertPopupOpen = true;
}

2. View层添加Popup表单

以Bootstrap Modal为例,实现弹窗编辑/插入:

<!-- 编辑弹窗 -->
<div class="modal fade" id="editModal" data-bs-backdrop="static" 
     visible.bind="IsEditPopupOpen" 
     bs-modal>
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title">编辑血液记录</h5>
                <button type="button" class="btn-close" click="{command: IsEditPopupOpen = false}"></button>
            </div>
            <div class="modal-body" Validation.Target="{value: SelectedBlood}" Validator.InvalidCssClass="has-error">
                <div class="mb-3">
                    <label class="form-label">产品</label>
                    <dot:ComboBox Value="{value: SelectedBlood.BloodProductID}" 
                                  DataSource="{value: ProductList}" 
                                  ItemValueBinding="{value: Value}" 
                                  ItemTextBinding="{value: Text}"
                                  Validation.Enabled="true" />
                    <dot:ValidationMessage For="{value: SelectedBlood.BloodProductID}" class="text-danger" />
                </div>
                <div class="mb-3">
                    <label class="form-label">备注</label>
                    <dot:TextBox Text="{value: SelectedBlood.Comments}" />
                </div>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-secondary" click="{command: IsEditPopupOpen = false}">取消</button>
                <button type="button" class="btn btn-success" click="{command: SaveEditedBlood()}" Validation.Target="{value: SelectedBlood}">保存</button>
            </div>
        </div>
    </div>
</div>

<!-- 插入弹窗(结构与编辑弹窗类似,绑定IsInsertPopupOpen即可) -->

<!-- GridView编辑按钮修改 -->
<ContentTemplate>
    <dot:LinkButton Click="{command: _parent.EditBlood(rowID)}">
        <bs:Icon Type="pencil" />
    </dot:LinkButton>
</ContentTemplate>

<!-- 原Add Blood按钮修改 -->
<bp:Button Text="Add Blood"
           Click="{command: OpenInsertPopup()}"
           Visible="{value: !IsInsertPopupOpen}"
           Validation.Enabled="false" />

这样就能实现点击按钮弹出表单编辑的模式,和DevExpress的PopupEditForm效果一致。

内容的提问来源于stack exchange,提问作者Tim Long

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 12:03:14