6

我有以下代码:

private void btnOK_Click(object sender, EventArgs e)
    {
        if (!string.IsNullOrEmpty(tbVendorName.Text))
        {
            VendorName = tbVendorName.Text;
            if (!string.IsNullOrEmpty(rtbVendorAddress.Text))
            {
                VendorAddress = rtbVendorAddress.Text;
                if (!string.IsNullOrEmpty(tbVendorEmail.Text))
                {
                    VendorEmail = tbVendorEmail.Text;
                    if (!string.IsNullOrEmpty(tbVendorWebsite.Text))
                    {
                        VendorWebsite = tbVendorWebsite.Text;
                        this.Close();
                    }
                    else
                    {
                        MessageBox.Show("Vendor Website Required");
                    }
                }
                else
                {
                    MessageBox.Show("Vendor email is required");
                }
            }
            else
            {
                MessageBox.Show("Vendor address is required");
            }
        }
        else
        {
            MessageBox.Show("Vendor name is required");
        }
    }

但它看起来很可怕。有没有更好的办法?或者甚至是使代码更具可读性的替代方法?

4

14 回答 14

8

更好的方法是掌握MVVM模式。您可以在那里创建一个 ViewModel 并在那里定义所有输入数据:

class VendorViewModel
{
    [Required]
    public string Name { get; set; }

    public string Website { get; set; }

    [Regex("regex for email")]
    public string Email { get; set; }

    [MaxLength(160)]
    public string Address { get; set; }
}

然后框架将在每个文本框或任何其他输入元素之后显示输入错误(如果有)。按钮的启用属性将根据正确验证的所有字段自动设置。

于 2013-09-02T07:10:09.803 回答
3

将它放在一个方法中并从该方法返回一个布尔值是否有效。

 private void btnOK_Click(object sender, EventArgs e)
{
    if(!Validate())
    {
        //Invalid
    }
    //Valid so set details
}

private bool Validate()
{
     if (!string.IsNullOrEmpty(tbVendorName.Text))
     {
          MessageBox.Show(...);
        return false;
     }

    return true;
}
于 2013-09-02T07:07:00.410 回答
2

我会为此任务构建一个像这样的专用方法:

private bool ValidateInput()
{
    bool ret = true;

    // List all the inputs you want, add a description for each one
    List<KeyValuePair<<string,string>) inputs = new Dictionary<string,string>();

    inputs.Add(new KeyValuePair<string,string>(tbVendorName.Text, "Vendor Name"));
    inputs.Add(new KeyValuePair<string,string>(tbVendorAddress.Text, "Vendor Address"));
    // .. and so on and so forth

    // Build a list of the empty ones 
    if(inputs.Any(i => string.IsNullOrEmpty(i.Key))
    {
        var msg = string.Join(", ", inputs.Where(i => string.IsNullOrEmpty(i.Key));
        MessageBox.Show(string.Format("The following inputs are required: {0}", msg);
        ret = false;
    }

    return ret;
}

易于阅读,并且该方法的作用立即清晰,同时非常紧凑。此外,如果需要,字段列表可能会从方法中移出并成为类字段(只需将列表作为参数传递就可以了)。许多方法在这里都是合理的。

用法:

private void btnOK_Click(object sender, EventArgs e)
{
    if (ValidateInput())
    {
        // They're all filled!
    }   
    else
    {
        // Something was missing.
    }
}
于 2013-09-02T07:17:40.127 回答
2

我在这里的答案中没有看到并且我喜欢的一种模式是使用yield return. 它不像基于属性的验证那样干净,但它很容易定制到很多场景并且适用于WinForms项目。

它还一次返回所有错误,而不是一次返回一个。

private void btnOK_Click(object sender, EventArgs e)
{
    var errors = Validate();

    if (errors.Any())
    {
        var sb = new StringBuilder();
        sb.AppendLine("The following errors were found:");
        foreach (var error in errors)
        {
            sb.AppendLine(error);
        }
        MessageBox.Show(sb.ToString());
        return;
    }
}

private IEnumerable<string> Validate()
{
    if (string.IsNullOrEmpty(tbVendorName.Text))
    {
        yield return "Vendor name missing";
    }
    if (string.IsNullOrEmpty(rtbVendorAddress.Text))
    {
        yield return "Vendor address missing";
    }
    if (string.IsNullOrEmpty(tbVendorEmail.Text))
    {
        yield return "Vendor email missing";
    }
}
于 2013-09-02T08:05:16.693 回答
1

您可以控制集合并检查它的类型,然后应用验证,例如

foreach(Control c in this.Controls)
 {
      //Check if it's input control    
      if(c is TextBox)
      {
             if (string.IsNullOrEmpty(c.Text))
              {
                 MessageBox.Show("Value Required");
               }
      }
  }
于 2013-09-02T07:10:49.630 回答
1

如果一切正常才能继续。你可以这样做:

private void btnOK_Click(object sender, EventArgs e)
{



   if (!string.IsNullOrEmpty(tbVendorEmail.Text))
       {
          VendorEmail = tbVendorEmail.Text;


       }
       else
       {
           MessageBox.Show("Vendor email is required");
       }
    if (!string.IsNullOrEmpty(tbVendorName.Text))
    {
        VendorName = tbVendorName.Text;

    }
    else
    {
        MessageBox.Show("Vendor name is required");
    }
    if (!string.IsNullOrEmpty(rtbVendorAddress.Text))
    {
        VendorAddress = rtbVendorAddress.Text;

    }
    else
    {
        MessageBox.Show("Vendor address is required");
    }

    if (!string.IsNullOrEmpty(tbVendorWebsite.Text))
        {
           VendorWebsite = tbVendorWebsite.Text;
           this.Close();
        }
        else
        {
        MessageBox.Show("Vendor Website Required");
        }


}

不知道 this.Close 做了什么,但您可以使用布尔值来检查它是否必须关闭。喜欢:

If(boolean=true)
{
   this.Close();
}

然后在一切正常时将布尔值设置为 true

必须有一个更简单的方法,但我不知道如何。

于 2013-09-02T07:24:44.917 回答
1

如果你想用常规来做if,你可以使用LINQ扩展方法:

bool valid = new [] { tbVendorName, rtbVendorAddress, tbVendorEmail, tbVendorWebsite }
                    .All(textBox => !string.IsNullOrEmpty(textBox.Text));

if(valid) 
{
    VendorName = tbVendorName.Text;          
    VendorAddress = rtbVendorAddress.Text;
    VendorEmail = tbVendorEmail.Text;
    VendorWebsite = tbVendorWebsite.Text;
}

扩展方法将.All(...)确定整个布尔表达式对于IEnumerable<T>.

此外,如果您想获得关于无效内容的准确结果,您可以使用规范模式

public interface ISpecification<TObject>
{
     // This holds the required field names
     IList<string> RequiredFields { get; }

     bool IsSatisfiedBy(TObject input);
}


public interface TextBoxSpecification : ISpecification<TextBox>
{
    // This holds a relation between field names and their display name
    private readonly IDictionary<string, string> _fieldMapping = new Dictionary<string, string> 
    {
        { "tbVendorName", "Vendor name" },
        { "rtbVendorAddress", "Vendor address" },
        { "tbVendorEmail", "Vendor email" },
        { "tbVendorWebsite", "Vendor Web site" }
    };

      private readonly IList<string> _requiredFields = new List<string>();

      private IList<string> RequiredFields { get { return _brokenRules; } }
      private IDictionary<string, string> { get { return _fieldMapping; } }

      public bool IsSatisfiedBy(TextBox input)
      {
          bool valid = true;

          // If the condition isn't satisfied, the invalid field's diplay name is
          // added to RequiredFields
          if(!string.IsNullOrEmpty(input)) 
          {
              valid = false;                  
              RequiredFields.Add(FieldMapping[input.Name]);
          }

          return valid;
      }
}

现在您的带有验证的事件处理程序将如下所示:

// Instantiating the specification.
ISpecification<TextBox> textBoxSpec = new TextBoxSpecification();

// Now, instead of just checking if it's not null or empty, the .All(...)
// extension method will execute the specification for all text boxes
bool valid = new [] { tbVendorName, rtbVendorAddress, tbVendorEmail, tbVendorWebsite }
                    .All(textBox => textBoxSpec.IsSatisfiedBy(textBox));

// If all specification were satisfied, you can assign the whole properties
if(valid) 
{
    VendorName = tbVendorName.Text;          
    VendorAddress = rtbVendorAddress.Text;
    VendorEmail = tbVendorEmail.Text;
    VendorWebsite = tbVendorWebsite.Text;
}
else
{
     // If not, generates a message box with a comma-separated 
     // list of required fields!
     MessageBox.Show
     (
            string.Format
            (
                  "The following fields are required: {0}",
                  textBoxSpec.RequiredFields.ToArray().Join(", ")
            )
     );  
}

在 Wikipedia 上了解有关规范模式的更多信息。

于 2013-09-02T07:20:16.833 回答
1

我相信用户输入验证应该通过出现在文本框或其他控件旁边的工具提示来完成,只要这些松散焦点。有很多验证框架。如果您在这里使用简单的 WPF,一个很好的例子: http: //www.codeproject.com/Articles/15239/Validation-in-Windows-Presentation-Foundation for WPF with MVVM: http: //www.codeproject.com/Articles /97564/Attributes-based-Validation-in-a-WPF-MVVM-Applicat for Win 表单看看这个 http://www.codeproject.com/Articles/10093/Validators-for-Windows-Forms-ValidationProvider-Co

于 2013-09-02T07:29:41.180 回答
1
private void btnOK_Click(object sender, EventArgs e)
        {
            var box = Controls.OfType<TextBox>().Any(x => !Validate(x));
            if (!box)
            {
                VendorName = tbVendorName.Text;
                VendorAddress = rtbVendorAddress.Text;
                VendorEmail = tbVendorEmail.Text;
                VendorWebsite = tbVendorWebsite.Text;
            }
        }

         private bool Validate(TextBox box)
         {
             if (!String.IsNullOrEmpty(box.Text)) return true;
                 MessageBox.Show(@"vender " + new List<string> {"name","email","website","address"}
                .Single(x => box.Name.ToLower().Contains(x)) + @" is required!...");
           return false;
         }
于 2013-09-02T08:04:22.007 回答
0

您可以通过使用必填字段验证器和正则表达式验证器来避免编写大量 javascript。谷歌会让你的生活变得更简单required field validator

于 2013-09-02T07:09:46.810 回答
0

您可以编写通用函数,使用 IsNullOrEmpty 验证值并设置 VendorName、VendorWebsite 等或显示错误消息。

于 2013-09-02T07:10:56.377 回答
0

您必须做的第一件事是创建一组验证类型,例如用于所有类型的电子邮件验证的一种方法,其返回类型应该是布尔值。每当您想验证任何电子邮件字段时。只需调用方法。如果您想检查多个字段的验证。只需使用以下语法。

if(Control1IsValid && Control2IsValid) {

}

于 2013-09-02T07:13:02.720 回答
0

假设您将应用TabOrder在您的(富)文本框上,并将错误消息保留在其标签属性中,您可以执行以下操作:

private void btnOk_Click(object sender, EventArgs e)
{
    var emptyTb = this.Controls.OfType<TextBox>()
        .Cast<Control>()
        .Union(this.Controls.OfType<RichTextBox>()
        .Cast<Control>())
        .OrderBy(tb => tb.TabIndex)
        .FirstOrDefault(tb => string.IsNullOrEmpty(tb.Text));
    if (emptyTb != null)
    {
        MessageBox.Show(emptyTb.Tag.ToString());
    }
}

注意:有一些性能成本,但方法的代码更容易阅读和维护。

于 2013-09-02T07:33:29.790 回答
0

虽然我更喜欢在输入必要的字段之前不允许单击“确定”的方法,但如果这只是“美化”代码的请求,您可以预先检查条件,即减少嵌套。

if (string.IsNullOrEmpty(tbVendorName.Text)) 
{
    MessageBox.Show("Vendor name is required");
    return;
}
if (string.IsNullOrEmpty(rtbVendorAddress.Text)) 
{
    MessageBox.Show("Vendor address is required");
    return;
}
if (string.IsNullOrEmpty(tbVendorEmail.Text)) 
{
    MessageBox.Show("Vendor email is required");
    return;
}
if (string.IsNullOrEmpty(tbVendorWebsite.Text)) 
{
    MessageBox.Show("Vendor Website Required");
    return;
}

VendorName = tbVendorName.Text;          
VendorAddress = rtbVendorAddress.Text;
VendorEmail = tbVendorEmail.Text;
VendorWebsite = tbVendorWebsite.Text;

附带说明一下,您目前只允许空格(您也不对格式进行任何类型的验证),因此您最好使用String.IsNullOrWhitespace()

于 2013-09-02T07:06:34.080 回答