使用ViewModels和ErrorProvider for WinForms的DataAnnotations

时间:2013-10-04 15:48:34

标签: winforms validation viewmodel data-annotations bindingsource

我正在尝试在实现新架构的同时为现有产品应用一些相当复杂的技术。其中大部分进展顺利,但我仍然需要将WinForms用于现有产品,因此需要使用ErrorProvider类来显示验证错误。 (新产品也可以通过WPF / MVC使用新架构,但我没有时间或资源从头开始完全重写以消除WinForms,因此技术组合)

新架构的基本布局如下:

Database -> Model (via NHibernate) -> ViewModel -> Form (using BindingSource)

所以我的问题是,如何在表单上的ValidationResult上对模型属性的失败DataAnnotation检查中使用ErrorProvider

我已经设法将ValidationResults的列表添加到表单中,但是将它们设置为特定控件正在暗示我没有为每个控件编写代码,我宁愿创建一个通用的方法来执行此操作BindingSource,可能是基础表格。

我知道如果DataAnnotations在ViewModel上,我可以更容易地做到这一点,但如果我这样做,那么如果对Model /进行了更改,我将不得不保持所有这些更新数据库表,这需要大量重复的代码。

我理解这个问题有点模糊,但考虑到这个跨越大部分架构的事实,我看不出更好的方法来解释它而不用编写大多数不相关的代码。如果您需要额外的信息,请询问,我会提供。

非常感谢。

1 个答案:

答案 0 :(得分:1)

不确定这是否有帮助,但看看是否将btn_Save改为这样,然后添加GetControlBoundToMember方法,我猜你的btnSave方法看起来类似于下面的方法。您还需要向表单添加一个ErrorProvider控件并将其命名为err1,并将可能位于groupbox中的任何控件移出groupbo并将它们放在表单上,​​除非您创建一个递归方法来搜索具有收集控件。

     private void btnSave_Click(object sender, EventArgs e)
    {
        if (_entity != null)
        {
            try
            {
                _service.Save(_entity.UpdateEntity());
            }
            catch (InvalidOperationException ex)
            {
                //do something here to display errors
                listBox1.Items.Clear();
                foreach (var r in _entity.Errors)
                {
                    listBox1.Items.Add(r.ErrorMessage);

                    foreach (var c in GetControlBoundToMember(r.MemberNames.ToList()))
                    {
                        err1.SetError(c, r.ErrorMessage);
                    }
                }
            }
        }
    }


    private IList<Control> GetControlBoundToMember(IList<string> memberNames)
    {

        List<Control> controls = new List<Control>();

        foreach (Control control in this.Controls)
        {
            foreach (var mn in memberNames)
            {
                foreach (Binding binding in control.DataBindings)
                {
                    if (binding.BindingMemberInfo.BindingField == mn) controls.Add(control);
                }
            }
        }

        return controls;
    }

AB