winforms Windows窗体应用程序中的文本框函数具有错误的返回类型[关闭]

44u64gxh  于 2023-10-23  发布在  Windows
关注(0)|答案(2)|浏览(115)

已关闭,此问题需要details or clarity。它目前不接受回答。
**想改善这个问题吗?**通过editing this post添加详细信息并澄清问题。

上个月关门了。
Improve this question
我最近开始学习.NET开发。我试图制作一个基本的SQL Server连接表单,但我一直遇到一个错误的返回类型错误,因为文本框函数接受SQL Server连接查询的用户名和密码。
我试图从文本框中接受用户输入,然后使用变量返回它们的值。

private void button1_Click(object sender, EventArgs e)
{
    //These are the variables I'm trying to pass to connect functions
    string User_name = textBox1_TextChanged(sender, e);
    string Pswd = textBox2_TextChanged(sender, e);

    string connection_string = null;
    MySqlConnection conn;
    connection_string = $"server=localhost;database=practice;uid={User_name};pwd={Pswd};";
    conn = new MySqlConnection(connection_string);
    try
    {
        conn.Open();
        MessageBox.Show("Connection Established !");
        conn.Close();
    }
    catch (Exception ex) 
    {
        MessageBox.Show($"Cannot open Connection ! \nErr code : {ex}");
    }
}

//Changed return type from default void to string
public string textBox1_TextChanged(object sender, EventArgs e)
{
    string User_name = textBox1.Text;
    return User_name;
}

public string textBox2_TextChanged(object sender, EventArgs e)
{
    string Pswd = textBox2.Text;
    return Pswd;
}

这就是现在的形式。

我得到的错误是:

  1. CS 0407“string Form1.textBox1_TextChanged(object,EventArgs)”的返回类型错误; File = Form1.Designer.cs ;线= 85
  2. CS 0407“string Form1.textBox2_TextChanged(object,EventArgs)”的返回类型错误; File = Form1.Designer.cs ;线= 99
    任何帮助都非常感谢。
r7xajy2e

r7xajy2e1#

看起来您试图从两个文本框(textBox1和textBox2)中获取值,以便在SQL Server连接字符串中使用它们。但是,您的代码存在一些问题。

  • TextChanged事件的事件处理程序应返回void*,而不是string。这些事件处理程序用于响应文本框中的更改,并且不需要返回值。相反,您应该在需要时直接从文本框访问值。

您不应该像这里这样显式调用**TextChanged* 事件处理程序 *:
string User_name = textBox1_TextChanged(sender, e);

相反,您应该直接在button1_Click事件处理程序中访问文本框的Text属性。

下面是代码的修改版本,可以解决这些问题:

C#

private void button1_Click(object sender, EventArgs e)
{
    // Get the values from the text boxes
    string User_name = textBox1.Text;
    string Pswd = textBox2.Text;
    string connection_string = null;
    MySqlConnection conn;
    connection_string = $"server=localhost;database=practice;uid={User_name};pwd={Pswd};";
    conn = new MySqlConnection(connection_string);
    try
    {
        conn.Open();
        MessageBox.Show("Connection Established !");
        conn.Close();
    }
    catch (Exception ex) 
    {
        MessageBox.Show($"Cannot open Connection ! \nErr code : {ex}");
    }
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
    // This event handler can remain as it is if you want to perform any specific actions
    // when the text in textBox1 changes.
}
private void textBox2_TextChanged(object sender, EventArgs e)
{
    // This event handler can remain as it is if you want to perform any specific actions
    // when the text in textBox2 changes.
}

我修改的这段代码中,button1_Click事件处理程序直接访问textBox1textBox2的Text属性,获取用户输入的值。当文本框中的文本发生更改时,如果您希望执行任何特定操作,则保留TextChanged事件处理程序。

如果你觉得这个有用,请标记我的答案:D

yc0p9oo0

yc0p9oo02#

模型-视图

在现代编程中,有一种趋势是将数据和对数据的操作(=模型)与数据的显示方式(=视图)分开。这样做的好处是,您可以更改模型,而不必显示视图。
例如,如果您有单独的过程来进行用户名-密码检查,然后您决定不再使用数据库,而是通过Internet发送数据,或者更简单,将其保存在CSV文件中,那么您不必更改视图。
类似地,如果您不想使用TextBox作为用户名,而是使用RichTextBox,您将更改视图,但不必更改模型。
另一个例子:你可以重复使用你的模型。例如,在一个管理员程序中,您希望在一个大表中显示所有用户名和密码,该程序可能会重用相同的模型。
最后但并非最不重要:可以在没有windows窗体的情况下对模型进行单元测试,并且您可以模拟您的模型,以便其他人可以测试您的用户界面。
要连接模型和视图,需要一个适配器类,通常称为ViewModel。
这三个类被缩写为MVVM。如果这对您来说是全新的,请考虑阅读一些关于MVVM的背景信息。

回到你的问题

模型

你在一个手术中做了太多的事情。这使得该过程难以理解,难以维护和测试,并且不可能重用。
你需要把你的代码分成更小的方法。为了提高可测试性,可以考虑创建只有一个目标的小类。让你的代码“SOLID”(同样,如果你不熟悉SOLID原则,做一些背景阅读)
首先,一些方法来创建一个开放的连接到数据库。这些方法易于理解,易于测试,易于维护和更改。

string ConnectionString => $"server=localhost;database=practice;uid={User_name};pwd={Pswd};";

MySqlConnection DefaultDatabaseConnection => this.CreateOpenDatabaseConnection(this.ConnectionString);

// Returns an open Connection to the database with connectionString
// throws InvalidOperationException if cannot open
MySqlConnection CreateOPenDatabaseConnection(string connectionString)
{
    MySqlConnection dbConnection = new MySqlConnection(connectionString);

    // open the database connection. 
    // Throws InvalidOperationException if cannot open        
    dbConnection.Open();
    return dbConnection;
}
catch (Exception ex) 
{
    MessageBox.Show($"Cannot open Connection ! \nErr code : {ex}");
}

检查提供的用户名-密码组合是否有效的方法。

bool IsUserNamePasswordCombinationValid(string userName, string password)
{
    // DbConnection implements IDisposable. So we should use "using"
    using (var dbConnection = this.DefaultDatabaseConnection)
    {
        return this.IsUserNamePasswordCombinationValid(dbConnection,
            string userName, string password);
    }
    // Dispose() will close the database connection
}

SqlCommand CreateSqlCommandCheckUserNamePassword(MySqlConnection connectedDb),
{
   const string parameterUserName = "@UserName";
   const string parameterPassword = "@Password";

   string sqlText = ... 
   // Todo: create sql text that returns 1 if userName / password combination
   // is in the database. user parameterUserName and parameterPassword as
   // parameters in the sqlText

   command.CommandText = sqlText;
   command.Parameters.Add(parameterUserName, userName);
   command.Parameters.Add(parameterPassword, password);
   return command;          
}

在所有这些小方法之后,通常只有一行,我们终于可以把所有的东西放在一起:

bool IsUserNamePasswordCombinationValid(MySqlConnection connectedDb,
     string userName, string password)
{
    // SqlCommand implements IDisposable, so we'll use using
    using (SqlCommand command = this.CreateSqlCommandCheckUserNamePassword(connectedDb)}
    {
        // we expect only one boolean, so we can use ExecuteScalar
        return (bool)command.ExecuteScalar();
    }
}

看起来有很多方法。幸运的是,大多数方法都是一行程序。他们只有一个具体的任务,没有别的。它们的功能易于理解,易于测试。如果发生更改,例如连接字符串或SqlText,则只需更改一个方法。
如果你计划重用这些代码,考虑把它们放在一个类中,例如:

class UserNamePasswordChecker
{
    public bool IsUserNamePasswordCombinationValid(string userName, string password)
    {
        // TODO: add code as described above.
        // all other methods can be private
    }

视图

只有访问文本框的方法,以及显示Ok / Not Ok的方法

string DisplayedUserName
{
    get => this.textBoxUserName.Text;
    set => this.textBoxUserName.Text = value;
}

string DisplayedPassword
{
    get => this.textboxPassword.Text;
    set => this.textboxPassword.Text = value;
}

bool DisplayedOk
{
    get => ...
    set => ...
}

后者可以显示一个文本框,或一个大的绿色复选标记的图像,或一个大的红十字。或者您可能需要一个通知操作员的MessageBox。
后者是一个很好的例子,说明了如何更改视图,而不必更改模型。

ViewModel

现在我们要做的就是为你的模型和视图创建一个适配器。请注意,处理button 1上的点击的事件处理程序也是viewModel。如果您决定不需要一个按钮,而是需要一个启动检查的菜单项,那么模型和视图都不应该改变。

// your Button1_Click is renamed to what it does, not who starts it
void CheckUserNamePassword(object sender, EventArgs e)
{
    var checker = new UserNamePasswordChecker();
    this.DisplayedOk = checker.IsUserNamePasswordOk(
        this.DisplayedUserName, this.displayedPassword);
}

摘要

因为我们使我们的过程SOLID,并且因为我们将模型从视图中分离出来,所以我们所有的方法都是小方法。每个方法都只有一个特定的任务。这样就很容易理解每个方法的作用。很容易测试这个简单的功能。很容易改变模型,而不必改变视图,反之亦然。很容易重用该模型,例如在程序中,管理员可以列出所有用户名和密码。
缺点:有很多种方法。
如果你想把所有的东西都放在一个大的方法中,变化就不大了。这不会提高效率很多;但它会降低可读性,更不用说其他优点了。

相关问题