我正在尝试编写游戏代码,我有一个 ASP(4 x 4)表,每个单元格中都有一个按钮。
当我们在 Page_Load() 上运行程序时,每个按钮都会获得一个随机数(显示在其按钮文本中)。 游戏目标的一部分是单击按钮,导致它们更改文本,我设法使用 button.click 方法来做到这一点, 我的问题是,每次单击时,虽然预期目标有效并且我们单击的按钮更改了其文本,但其余按钮会重新加载并获取其按钮文本的新值。
(Page_Load 再次运行),有什么提示可以解释为什么会发生这种情况以及处理此问题以实现我的目标的最佳方法是什么?
这是我的 main.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="main.aspx.cs" Inherits="HM1.main" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Table ID="GameTable" runat="server"></asp:Table>
</div>
</form>
</body>
</html>
这是我的 main.aspx.cs (请注意,for循环中的所有内容只是随机放置按钮1-15的代码,并且按钮右上角的数字16是不可见的)
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace HM1
{
public partial class main : System.Web.UI.Page
{
public Button[,] buttons;
protected void Page_Load(object sender, EventArgs e)
{
buttons = new Button[4, 4];
int[] buttonMumbers = new int[buttons.Length];
for (int z=0; z < buttonMumbers.Length; z++)
{
buttonMumbers[z] = z + 1;
}
var rng = new Random();
var indexs = buttonMumbers.Select(x => rng.NextDouble()).ToArray();
Array.Sort(indexs, buttonMumbers);
int counter = 0;
for(int i = 0; i <buttons.GetLength(0); i++){
var row = new TableRow();
for(int j = 0; j<buttons.GetLength(1); j++){
var cell = new TableCell();
var button = buttons[i, j] = new Button();
button.Width = 75;
button.Height = 75;
button.BackColor = Color.DarkCyan;
button.Click += new EventHandler(this.BtnClick);
if(i == j && i==3)
{
break;
}
if (buttonMumbers[counter] == 16)
{
counter++;
button.Text = buttonMumbers[counter].ToString();
}else {
button.Text = buttonMumbers[counter].ToString();
counter++;
}
cell.Controls.Add(button);
row.Controls.Add(cell);
}
GameTable.Controls.Add(row);
}
buttons[3, 3].Visible = false;
}
public void BtnClick(Object sender, EventArgs e) {
Button clickedButton = (Button)sender;
clickedButton.Text = "clicked!";
}
}
}
您所看到的行为不仅是正确的,而且实际上是设计使然。
因此,点击网页上的任何按钮都会导致页面加载事件首先运行,然后按钮代码存根将运行。
因此,简单的解决方案是放置这样的页面加载代码,该代码仅在真正的首页加载上运行,即在该页面加载事件中具有/添加/使用此附加 if () 代码:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
// the real first page load code goes here
string strSQL = @"SELECT * FROM tblHotelsA
ORDER BY HotelName";
GVHotels.DataSource = General.MyRst(strSQL);
GVHotels.DataBind();
}
}
因此,在上面,我加载了带有一些数据的 GridView。如果我不将该代码放在 Is not post back if 块内,那么每次单击按钮时都会重新加载 GridView。
对于简单的组合框来说,这可能是一个问题。如果页面上有一个组合框(下拉列表),并且在页面加载时您会加载带有选项的组合框?
然后加载代码将每次运行并覆盖用户在组合框中的选择。那么,这再次意味着/建议/显示/暗示页面加载事件可以自由地用于加载和设置代码和值?
请记住,每次发生回发时都会运行此类代码。因此,按理说,大约 99% 的页面都需要上述所有重要的 !IsPostBack 存根。
事实上,我很乐意指出,如果没有 !IsPostBack 代码存根,您真的无法构建一个有效的 Web 表单页面。因为在几乎所有情况下,我们都希望一些页面设置代码运行一次,并且仅在第一次实际页面加载时运行。如果此类设置代码每次在页面加载时运行,则此类代码将覆盖您在该加载事件中设置的控件和对象的值。如前所述,任何组合框、复选框,甚至触发回发的按钮都意味着首先运行页面加载,然后运行给定控件的代码存根。
因此,如上所述的简单解决方案是使用上面的 !IsPostBack 代码存根。