ASP.NET C#,需要按两次按钮才能使某事发生。

9

我有一个Web应用程序,问题是标签中的文本在第一次单击时不会更新,我需要点击两次按钮。我调试了代码,并发现直到第二次单击后,标签才能接收到数据。

这是我的代码:

System.Data.SqlClient.SqlCommand command = new System.Data.SqlClient.SqlCommand();
System.Data.SqlClient.SqlConnection connection;
string CommandText;
string game;
string modtype;
bool filter;
protected void Page_Load(object sender, EventArgs e)
{

    labDownloadList.Text = null;

    //Session variables:
    if (Session["Game"] != null)
    {
        game = Convert.ToString(Session["Game"]);
    }
    if (Session["ModType"] != null)
    {
        modtype = Convert.ToString(Session["ModType"]);
    }
    if (Session["FilterBool"] != null)
    {
        filter = Convert.ToBoolean(Session["FilterBool"]);
    }
    string ConnectionString = "Data Source=.\\SQLEXPRESS;AttachDbFilename=C:\\inetpub\\wwwroot\\stian\\App_Data\\Database.mdf;Integrated Security=True;User Instance=True";
    connection = new System.Data.SqlClient.SqlConnection(ConnectionString);
    System.Data.SqlClient.SqlDataReader reader;
    command = connection.CreateCommand();
    connection.Open();
    CommandText = "SELECT * FROM Command";
    if (filter)
    {
        CommandText = "SELECT * FROM Command WHERE Game='" + game + "' AND Type='" + modtype + "'";
    }
    command.CommandText = CommandText;
    reader = command.ExecuteReader();
    labDownloadList.Text = "";
    while (reader.Read())
    {
        string game = reader.GetString(1);
        string author = reader.GetString(2);
        string downloadlink = reader.GetString(3);
        string size = reader.GetString(4);
        string description = reader.GetString(5);
        string version = reader.GetString(6);
        string screenshotlink = reader.GetString(7);
        Int64 AmountDownloaded = reader.GetInt64(8);

        labDownloadList.Text += "Game: " + game + "<br>";
        labDownloadList.Text += "Author: " + author + "<br>";
        labDownloadList.Text += "Size: " + size + "<br>";
        labDownloadList.Text += "Description: " + description + "<br>";
        labDownloadList.Text += "Version: " + version + "<br>";
        labDownloadList.Text += "<img src='" + screenshotlink + " /><br>";
        labDownloadList.Text += "Downloaded: " + AmountDownloaded + " times<br><hr>";
        labDownloadList.Text += "<a href='" + downloadlink + "'>Download</a><br>";
    }
}

protected void Page_UnLoad(object sender, EventArgs e)
{
    Session["Game"] = game;
    Session["ModType"] = modtype;
    Session["FilterBool"] = filter;
    connection.Close();
}

protected void btnFilter_Click(object sender, EventArgs e)
{
    game = lstGames.SelectedValue;
    modtype = lstTypeMod.SelectedValue;
    filter = true;
}

一些关于编程的评论:
  • 你不需要使用Convert.ToString(Session["game"])。Session[name]是一个对象,所以你只需要将其强制转换为字符串:(string)Session["game"]
  • 你应该研究一下参数化SQL,因为你很容易受到注入攻击的影响。
- Aaron Powell
一定要研究参数化 SQL。 - Mitch Wheat
11个回答

11

需要明确的是,按钮点击事件发生在 Page_Load 事件之后,这意味着过滤器不会被应用于第一个 postback。过滤器将在第二个 postback 后更新,并且您将看到筛选效果。使您的代码正常工作的最简单的更改是将所有代码移到 OnPreRender 中,以便重新加载发生在按钮点击事件之后。

然而,更清晰的解决方案可能是将其移入 LoadData 函数,并在 PageLoad 不是 postback 时调用该函数。在更新过滤器后,还应在按钮点击事件中调用它。这样可以防止在任何不需要重新加载数据的 postback 页面循环中对数据库进行调用:


protected void Page_Load(object sender, EventArgs e)
{    
    if (!Page.IsPostBack)
        {   
             LoadData();
        }
}

private void LoadData()
{
    labDownloadList.Text = null;
    //Session variables:    
    if (Session["Game"] != null)
    ...
}

protected void btnFilter_Click(object sender, EventArgs e)
{    
    game = lstGames.SelectedValue;
    modtype = lstTypeMod.SelectedValue;
    filter = true;
    LoadData();
}

这段代码是一个ASP.NET页面的C#代码,它包含了三个方法。`Page_Load`方法在页面加载时执行,并检查页面是否已经重新加载。如果是第一次加载页面,则调用`LoadData()`方法。 `LoadData()`方法负责为“labDownloadList”变量设置一个空值,然后检查名为“Game”的会话变量是否为空。`btnFilter_Click`方法被触发当用户单击了一个名为“btnFilter”的按钮,该方法设置一些变量,并再次调用`LoadData()`方法。

对于一名初学者ASP.Net开发人员的最后一条快速建议是,要彻底了解页面生命周期。了解页面上的事件序列是必不可少的。祝好运。


谢谢您的回答。不过,更清晰的做法是明确指出BUTTON的预渲染,而不是PAGE。 - John D

7

微软对页面生命周期的概述可能有助于理解流程(并解决您的问题)。


1
这是一篇非常棒的文章,我经常向人们推荐它。 - Aaron Powell

6

因此,在您的代码中,一旦单击按钮,页面加载事件将触发并设置数据,然后btnClick事件将触发并更改数据。但是,数据已经以其旧形式绑定。这就是为什么需要两次点击才能使其正常工作的原因。

如果将相同的page_load代码放入page_loadcomplete事件中,则会在btnClick事件之后发生。这应该会产生所需的结果。


2
我看不到典型的情况。
if (!Page.IsPostBack)
{
   ...
}

在你的Page_Load方法中,这意味着每次加载页面时都会发生数据绑定,很可能导致你的问题。我建议将其添加到代码中并查看是否解决了该问题。


1

我在我的页面上遇到了相同的问题。每次我都需要点击两次才能使其正常工作。这是由于某些文本框和下拉列表设置为自动回发所导致的。一旦我删除了自动回发,单击就可以顺利触发。


1

JackCom,你的解决方案很有效!谢谢。我会学习页面生命周期。 我必须补充说明,我只有软件开发方面的经验,这个秋季我才刚开始学习Web开发。


0

ASP.Net有时候会做出非常奇怪的事情。今天我也遇到了同样的问题。我发现我在一个文本框上加了AutoPostBack="true",尽管它没有实现我想要的功能,但我忘记从标记中删除AutoPostBack。当我点击同一行中的按钮时,第一次点击会导致两个postbacks,但不会触发按钮事件。第二次点击按钮时,按钮单击事件才会触发。当我从标记中找到多余的AutoPostBack时,按钮事件就开始在第一次单击时触发。人们可能会认为文本框与按钮毫无关联,除了按钮单击事件引用了文本框的内容。


0

将 VB 项目转换为 C# 后,我遇到了双击事件问题。发现转换器只转换了代码后面的内容,而没有转换 ascx 和 aspx 页面代码,这些页面仍然是 language="vb"。逐个将其转换为 C# 并指定语言为 language="cs" 即可解决问题。


0

我卡在这个问题上一周了。最后,我把代码放到TextChanged事件中的Button_Click事件后面,结果它奏效了。按下按钮会使焦点离开TextBox,从而在未发生Button_click事件时触发该事件。非常笨拙。我不喜欢它。

我遇到了一篇有趣的文章,但实际上并没有为我工作,但我很高兴阅读它: 输入和按钮单击事件

在其他情况下可能会起作用。


0
我遇到了这个问题,因为我在页面之间使用了“Server.Transfer”。当我改用“Response.Redirect”时,问题得到解决。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接