2016-04-25 65 views
0

我想创建一个简单的输入对话框。所以我添加了Windows来自我的应用程序,并在该窗口中放置了一个标签,一个文本框和一个按钮;现在,使用构造函数可以很容易地使用预定义的值填充我的控件的所需属性,并使用result返回输入的值;将用户定义的方法传递给构造函数

public partial class GeneralInputForm : Form 
{ 
    public string result = ""; 
    public GeneralInputForm(string label, string defaultValue = "") 
    { 
     InitializeComponent(); 
     label1.Text = label; 
     textBox1.Text = defaultValue; 
    } 

    private void button1_Click(object sender, EventArgs e) 
    { 
     result = textBox1.Text; 
     Close(); 
    } 
} 

现在创建一个from和使用所需值填充参数的实例;

GeneralInputForm formInput = new GeneralInputForm("Please enter your age:"); 
formInput.ShowDialog(); 

//formInput.result  holds the value 

我的问题引发了这里;如果我想检查用户在GeneralInputForm本身的文本框中输入的值的有效性(而不是稍后通过检查result字段来实例化表单时)该怎么办?我的意思是在C#中有这样的功能(可能是委托),以便用户自己可以定义一个方法并将其作为构造函数的参数之一传递,该方法将检查值,以确保其成功被解析为intfloatstring

我不想在我的构造函数中添加一个名为variableType的丑陋字符串参数,并要求用户说出他是否需要'int'或'float'或'string'或其他什么,然后通过检查值的variableType,写了不同的陈述,以确保输入的文本可以被成功解析为int或浮动或字符串(这将是一个丑陋的和有限的解决方案)

+0

由于您已经将代表视为一种选择,您为什么不最终使用它们? – Servy

+0

我不明白,如果你期望被调用的表单执行任何转换或不。看起来你不会要求这个工作被被调用的表单执行,但是你想要一个GenericInputForm调用回来检查输入有效性的委托。我错了吗? – Steve

+0

你已经得到了你的答案,但是你没有给出反馈。 –

回答

0

感谢大家的答案;我使用代表完成了这个简单明了的解决方案;

public partial class SimpleInputForm : Form 
{ 
    public string Value = ""; 
    public delegate bool VerifyDel(string input); 
    private VerifyDel Methods; 
    public SimpleInputForm(string lable, VerifyDel method) 
    { 
     InitializeComponent(); 
     label1.Text = lable; 
     Methods = new VerifyDel(method); 
    } 
    private void button1_Click(object sender, EventArgs e) 
    { 
     if (Methods(textBox1.Text)) 
     { 
      Value = textBox1.Text; 
      Close(); 
     } 
    } 
} 

现在我显示窗体用用户定义的功能来评估输入;

SimpleInputForm simpleInput = new SimpleInputForm("Enter your age:", (input => { 
    try 
    { 
     int age = int.Parse(input); 
     return true; 
    } 
    catch 
    { 
     MessageBox.Show("Invalid value for age!"); 
     return false; 
    } 
})); 

//simpleInput.Value  holds the input value 
1

更改GeneralInputFormGeneralInputForm<T>。是一个通用类,就像List<String>

,可以使用两个领域Func键一到文本转换为你想要的对象和一个检查返回就像这样:

public partial class GeneralInputForm<T> : Form 
{ 
    public T result = default(T); 
    Func<T, Boolean> check = (input) => true; // Default check 
    Func<String, T> cast = null; // Default cast 

    public GeneralInputForm(string label, string defaultValue = "", Func<String, T> cast, Func<T, Boolean> check) 
    { 
     InitializeComponent(); 
     label1.Text = label; 
     textBox1.Text = defaultValue; 
     if(check != null) 
      this.check = check; 
     this.cast = cast; 
    } 

    private void button1_Click(object sender, EventArgs e) 
    { 
     if(cast != null) 
     { 
      T casted = cast(textBox1.Text); 

      if(casted != null && check(casted)){ 
       result = textBox1.Text; 
       Close(); 
      } 
     } 
    } 
} 

而且你可以使用它像这样:

Func<String, int> cast = (input) => int.Parse(input); 
Func<int, Boolean> check = (input) => input > 0; 
GeneralInputForm<int> form = new GeneralInputForm<int>("Enter a number:", "1", cast, check); 
form.ShowDialog(); 
//etc.... 

More info about Generics.

这种做事的方式被命名为依赖注入,这种方法是构造器注入类型。 More info.

+0

无论如何,您的答案是更好的.... – Steve

+0

这一行: public T result =“”; 我得到这个错误:不能隐式地将类型字符串转换为T – wiki

+0

你是对的,复制粘贴你知道的错误...已更新。 –

0

您不需要将它作为参数传递。验证函数可以使用继承进行覆盖。

public partial class GeneralInputForm : Form 
    { 
     // Returns true if this text is valid for a textbox 
     protected virtual bool IsValid(string text) 
     { 
      return true;     // default behaviour 
     } 

     private void button1_Click(object sender, EventArgs e) 
     { 
      if (IsValid(textBox1.Text)) 
      { 
       result = textBox1.Text;  // ok 
       Close(); 
      } 
      else 
      { 
       // Show error message 
      } 
     } 
    } 

现在你可以创建一个形式,定制验证文本框,通过重写(即替换)和isValid()函数:

public partial class SpecificInputForm : GeneralInputForm 
    { 
     // Blank textboxes are not valid, and are restricted to 31 characters 
     protected override bool IsValid(string text) 
     { 
      if (string.IsNullOrWhitespace(text)) 
       return false; 

      return (text.Length < 32); 
     } 
    } 
0

虽然@奥斯卡的答案会工作的,令一般是有点坏主意,因为Winforms设计者反感他们(试图从该形式继承,你会看到)。

我可能会做它,以便它不是说是通用的形式,而是一种方法:

public partial class GeneralInputForm : Form 
{ 
    private GeneralInputForm() // Private constructor 
    { 
    InitializeComponent(); 
    } 

    public static bool TryGetValue<T>(
      string label, 
      string defaultValue, 
      Func<T, bool> check, 
      out T result 
     ) where T : IConvertible 
    { 
    result = default(T); 
    using (var frm = new GeneralInputForm()) 
    { 
     frm.label1.Text = label; 
     frm.textBox1.Text = defaultValue; 
     frm.Closing += (o, e) => 
     { 
     var myForm = (GeneralInputForm) o; 
     // User closed not clicking the button? 
     if (myForm.DialogResult != DialogResult.OK) 
      return; 
     try 
     { 
      var checkval = (T) Convert.ChangeType(myForm.textBox1.Text, typeof (T)); 
      if (!check(checkval)) 
      e.Cancel = true; 
     } 
     catch 
     { 
      e.Cancel = true; 
     } 

     }; 
     if (frm.ShowDialog() == DialogResult.OK) 
     { 
     result = (T)Convert.ChangeType(frm.textBox1.Text, typeof (T)); 
     return true; 
     } 
    } 
    return false; 
    } 

    private void button1_Click(object sender, EventArgs e) 
    { 
    // Don't use `Close()` on modal forms, it's always better to 
    // return a dialog result. This will close the form aswell 
    DialogResult = DialogResult.OK; 

    } 
} 

然后使用它像:

int result; 
if(GeneralInputForm.TryGetValue("Enter an integer over 10", 
           "10", 
           (x) => x > 10, 
           out result)) 
    MessageBox.Show(result.ToString()); 
else 
    /* User closed the form by other means */ 

或者:

string result; 
if (GeneralInputForm.TryGetValue("Enter \"Hello\"", 
           "Goodbye", 
           (x) => x == "Hello", 
           out result)) 

这不会让你通过点击button1关闭窗体,除非值是正确的,但会让你c通过其他方式失去它(alt + f4,点击x等)。如果按钮关闭,它将返回true;如果不是,则返回false(您可以在此处放置一个Cancel按钮)。

您也可以使defaultValue参数是T型和分配defaultValue.ToString()

一个消息可以显示在Closing代表用户的文本,如果值是无效的,或者你可以让你自己逻辑

这要求TIConvertible,但是关于具有Parse方法的任何类型是

+0

尽管设计人员不能使用泛型窗体的派生类,但依赖注入方式允许您避免继承,因为您可以为表单提供所需的所有功能。 –

相关问题