c#有更好的方法来验证用户输入

时间:2013-09-02 07:04:03

标签: c# validation if-statement

我有以下代码:

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");
        }
    }

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

14 个答案:

答案 0 :(得分:5)

更好的方法是掌握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; }
}

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

答案 1 :(得分: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;
}

答案 2 :(得分: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.
    }
}

答案 3 :(得分: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");
               }
      }
  }

答案 4 :(得分: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(", ")
            )
     );  
}

Learn more about specification pattern on Wikipedia.

答案 5 :(得分: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

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

答案 6 :(得分:1)

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

答案 7 :(得分: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;
         }

答案 8 :(得分:1)

我在答案中没有看到的一种模式,我喜欢使用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 (string s in errors)
        {
            sb.AppendLine(s);
        }
        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";
    }
}

答案 9 :(得分:0)

虽然我更喜欢一种简单地禁止单击“确定”直到输入必要字段的方法,但是如果这只是一个“非常”代码的请求,则可以预先检查条件,即减少嵌套。 / p>

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()

答案 10 :(得分:0)

您可以通过使用必填字段验证程序和正则表达式验证程序来避免编写大量的JavaScript。这将使你的生活变得更加简单,只需谷歌required field validator

答案 11 :(得分:0)

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

答案 12 :(得分:0)

你要做的第一件事就是制作一组验证类型,就像所有类型的电子邮件验证的一种方法一样,返回类型应该是布尔值。每当您想验证任何电子邮件字段时。只需要调用方法。如果你想检查多个字段的验证。只需使用以下语法。

if(Control1IsValid&amp;&amp; Control2IsValid) {

}

答案 13 :(得分: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());
    }
}

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