为什么我的 itemCommand DataGrid 事件仅在第二次单击网格控件中的项目时触发?
Why does my itemCommand DataGrid event only fire on the second click of an item in the grid control?
我的 Web 表单数据网格响应点击事件时遇到问题。请允许我解释一下:
- 第一次加载页面时,会为用户填写一个下拉列表以 select 一个项目。
当用户 select 在下拉列表中选择一个项目时,会出现一个数据网格(称为 tmdg)(加载第二页),其中包含 ButtonColumns。当用户 select 在数据网格中的 ButtonColumns 之一中按下按钮时,按钮的值从 false 翻转为 true(或从 true 翻转为 false,具体取决于其起始值)。在 Page_Load 事件中,如果 Page.IsPostBack==true,我将事件处理程序分配给数据网格 (tmdg),如下所示:
tmdg.ItemCommand += Tmdg_ItemCommand;
Tmdg_ItemCommand 是调用 Save() 的方法,它翻转数据表并最终翻转数据网格单元格值。
这一切都适用于第一次单击数据网格。
但是,对于随后单击数据网格,button.DataTextField 值仅在第二次单击网格时翻转。 (本质上是 "double click" 而不是单击)。我的目标是为每个单击事件翻转 ButtonColumn 中单元格的值。
请注意:第一次点击数值翻转成功的格子后,如果我可以点击单元格(5,6)没有任何反应,如果我点击单元格(7,2)我会得到一个翻转该单元格的 (7,2)。同样,我可以在没有任何反应的情况下再次单击 (5,2),然后再次单击 select (5,2) 进行翻转。 (这就是我所说的 "double click")
其他说明:
我尝试在整个应用程序的多个位置分配事件处理程序(在页面的 OnInit Page_Load 之前;或在 UpdatePanel 的 Panel_Init 方法中;或不管if Page.IsPostBack 在 Page_Load 中;或在 Page_Load)
之后
datagrid 是一个动态加载的控件,放置在 Panel 上,而 Panel 又放置在 UpdatePanel 上。
我会尽量不在这里放置大量混乱的代码,但确实想为您提供一些东西。为了简洁起见,我对它进行了一些编辑。
::::Push.aspx::::
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Push.aspx.cs" Inherits="TMUWF.Push" MasterPageFile="~/Site.Master" %>
<asp:Content ID="Content3" ContentPlaceHolderID="MainContent" Runat="Server">
<asp:DropDownList ID="DropDownList1"
OnSelectedIndexChanged="DropDownList1_SelectedIndexChanged"
runat="server"
AutoPostBack="True"
AppendDataBoundItems="true"
OnMouseDown="this.size=10;"
OnFocusOut="this.size=1;"
OnDblClick="this.size=1;"
>
</asp:DropDownList>
<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional" OnInit="Panel_Init">
<contenttemplate>
<h3 id="div-Col-Title">Node</h3>
<asp:Panel runat="server" ID="Panel1">
<div id="div-Row-Title"><h3 >Channel</h3></div>
</asp:Panel>
</contenttemplate>
</asp:UpdatePanel>
</asp:Content>
::::Push.aspx.cs::::
namespace TMUWF
{
public partial class Push : System.Web.UI.Page
{
DataGrid tmdg = new DataGrid
{
AutoGenerateColumns = false,
CssClass = "gvClass push"
};
DataTable TraffMat = new DataTable();
DataView TraffMatView;
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
UpdatePanel1.Visible = false;
FillDropDown();
}
else if (!(Session["PushIntId"] == null))
{
int IntID = GetSession();
BindGrid(IntID);
// instead of checking for null, just remove the event handler
tmdg.ItemCommand -= Tmdg_ItemCommand;
// Manually register the event-handling method for the item click
tmdg.ItemCommand += Tmdg_ItemCommand;
}
}
private void FillDropDown()
{ //redacted, pulls values from database for dropdownlist
}
private void BindGrid(int IntID)
{
if (Panel1.Controls.Contains(tmdg))
{
Panel1.Controls.Remove(tmdg);
}
SaveSession(IntID);
tmdg = BuildTmdg(tmdg, TraffMat);
TraffMatView = new DataView(TraffMat);
// Set the data source and bind to the Data Grid control.
tmdg.DataSource = TraffMatView;
tmdg.DataBind();
if (!Panel1.Controls.Contains(tmdg))
{
Panel1.Controls.Add(tmdg);
}
UpdatePanel1.Visible = true;
UpdatePanel1.Update();
}
private DataGrid BuildTmdg(DataGrid dg, DataTable dt)
{
dg.Columns.Clear();
for (int col = 0; col<17; col++)
{
if (col == 0)
{
BoundColumn bc = new BoundColumn
{
HeaderText = " ",
DataField = dt.Columns[col].ToString(),
ReadOnly = true
};
dg.Columns.Add(bc);
}
else
{
ButtonColumn btnc = new ButtonColumn
{
HeaderText = col.ToString(),
ButtonType = ButtonColumnType.PushButton,
DataTextField = dt.Columns[col].ToString(),
CommandName = col.ToString()
};
dg.Columns.Add(btnc);
}
}
return dg;
}
private void Tmdg_ItemCommand(object source, DataGridCommandEventArgs e)
{
Save((Int32)Session["PushIntID"], Convert.ToInt32(e.CommandName), e.Item.DataSetIndex+1);
}
private void Save(int IntID, int col, int row)
{
int newIntID = IntID;
int newcol = col;
int newrow = row;
// Apply changes to DataTable
string newVal = UpdateDataTable(IntID, col, row);
// Apply changes to Database
int rowsAffected = Apply(IntID, col, row, newVal);
// Bind DataTable to TMDG
BindGrid(IntID);
}
private string UpdateDataTable(int IntID, int col, int row)
{
row--;
string val = TraffMat.Rows[row][col].ToString();
if (val == "False")
{
val = "True";
TraffMat.Rows[row][col] = val;
}
else
{
val = "False";
TraffMat.Rows[row][col] = val;
}
TraffMat.AcceptChanges();
SaveSession(IntID);
TraffMatView = new DataView(TraffMat);
return val;
}
private int Apply(int IntID, int col, int row, string NewVal)
{ //redacted, saves values to database
}
protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
{ //redacted, fills DataTable from database, calls SaveSession, calls BindGrid
}
private int GetSession()
{ //redacted, gets session state
}
private void SaveSession(int IntID)
{ //redacted, sets session state
}
}
}
在我看来,当我在 BindGrid() 的两个 "if" 语句中设置断点时,第一个 "if" 经常被跳过,这意味着 Panel1 在那一刻不包含我的数据网格 tmdg及时。这个 "if" 在被忽略的 "first-click" 中被特别跳过。
如果您需要我提供更多信息,请告诉我!
我希望你们中的一个能弄清楚我做错了什么!!
任何和所有评论表示赞赏..
我没有在 Push.aspx.cs 中实例化数据网格 tmdg,而是将其添加到 Push.aspx 并且每次都会触发点击事件。我不确定为什么这在 .aspx 中有效但在 .aspx.cs 文件中无效。
后面有新代码说明...
:::::Push.aspx:::::(此处添加了数据网格)
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Push.aspx.cs" Inherits="TMUWF.Push" MasterPageFile="~/Site.Master" %>
<asp:Content ID="Content3" ContentPlaceHolderID="MainContent" Runat="Server">
<asp:DropDownList ID="DropDownList1"
OnSelectedIndexChanged="DropDownList1_SelectedIndexChanged"
runat="server"
AutoPostBack="True"
AppendDataBoundItems="true"
OnMouseDown="this.size=10;"
OnFocusOut="this.size=1;"
OnDblClick="this.size=1;"
>
</asp:DropDownList>
<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional" OnInit="Panel_Init">
<contenttemplate>
<h3 id="div-Col-Title">Node</h3>
<asp:Panel runat="server" ID="Panel1">
<div id="div-Row-Title"><h3 >Channel</h3></div>
<asp:DataGrid ID="tmdg" CssClass="gvClass push" AutoGenerateColumns="false" runat="server" >
</asp:DataGrid>
</asp:Panel>
</contenttemplate>
</asp:UpdatePanel>
</asp:Content>
:::::Push.aspx.cs:::::(此处删除了数据网格)
//DataGrid tmdg = new DataGrid
//{
// AutoGenerateColumns = false,
// CssClass = "gvClass push"
//};
关于 WHY 的想法表示赞赏。
我的 Web 表单数据网格响应点击事件时遇到问题。请允许我解释一下:
- 第一次加载页面时,会为用户填写一个下拉列表以 select 一个项目。
当用户 select 在下拉列表中选择一个项目时,会出现一个数据网格(称为 tmdg)(加载第二页),其中包含 ButtonColumns。当用户 select 在数据网格中的 ButtonColumns 之一中按下按钮时,按钮的值从 false 翻转为 true(或从 true 翻转为 false,具体取决于其起始值)。在 Page_Load 事件中,如果 Page.IsPostBack==true,我将事件处理程序分配给数据网格 (tmdg),如下所示: tmdg.ItemCommand += Tmdg_ItemCommand;
Tmdg_ItemCommand 是调用 Save() 的方法,它翻转数据表并最终翻转数据网格单元格值。
这一切都适用于第一次单击数据网格。 但是,对于随后单击数据网格,button.DataTextField 值仅在第二次单击网格时翻转。 (本质上是 "double click" 而不是单击)。我的目标是为每个单击事件翻转 ButtonColumn 中单元格的值。
请注意:第一次点击数值翻转成功的格子后,如果我可以点击单元格(5,6)没有任何反应,如果我点击单元格(7,2)我会得到一个翻转该单元格的 (7,2)。同样,我可以在没有任何反应的情况下再次单击 (5,2),然后再次单击 select (5,2) 进行翻转。 (这就是我所说的 "double click")
其他说明:
我尝试在整个应用程序的多个位置分配事件处理程序(在页面的 OnInit Page_Load 之前;或在 UpdatePanel 的 Panel_Init 方法中;或不管if Page.IsPostBack 在 Page_Load 中;或在 Page_Load)
之后
datagrid 是一个动态加载的控件,放置在 Panel 上,而 Panel 又放置在 UpdatePanel 上。
我会尽量不在这里放置大量混乱的代码,但确实想为您提供一些东西。为了简洁起见,我对它进行了一些编辑。
::::Push.aspx::::
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Push.aspx.cs" Inherits="TMUWF.Push" MasterPageFile="~/Site.Master" %>
<asp:Content ID="Content3" ContentPlaceHolderID="MainContent" Runat="Server">
<asp:DropDownList ID="DropDownList1"
OnSelectedIndexChanged="DropDownList1_SelectedIndexChanged"
runat="server"
AutoPostBack="True"
AppendDataBoundItems="true"
OnMouseDown="this.size=10;"
OnFocusOut="this.size=1;"
OnDblClick="this.size=1;"
>
</asp:DropDownList>
<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional" OnInit="Panel_Init">
<contenttemplate>
<h3 id="div-Col-Title">Node</h3>
<asp:Panel runat="server" ID="Panel1">
<div id="div-Row-Title"><h3 >Channel</h3></div>
</asp:Panel>
</contenttemplate>
</asp:UpdatePanel>
</asp:Content>
::::Push.aspx.cs::::
namespace TMUWF
{
public partial class Push : System.Web.UI.Page
{
DataGrid tmdg = new DataGrid
{
AutoGenerateColumns = false,
CssClass = "gvClass push"
};
DataTable TraffMat = new DataTable();
DataView TraffMatView;
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
UpdatePanel1.Visible = false;
FillDropDown();
}
else if (!(Session["PushIntId"] == null))
{
int IntID = GetSession();
BindGrid(IntID);
// instead of checking for null, just remove the event handler
tmdg.ItemCommand -= Tmdg_ItemCommand;
// Manually register the event-handling method for the item click
tmdg.ItemCommand += Tmdg_ItemCommand;
}
}
private void FillDropDown()
{ //redacted, pulls values from database for dropdownlist
}
private void BindGrid(int IntID)
{
if (Panel1.Controls.Contains(tmdg))
{
Panel1.Controls.Remove(tmdg);
}
SaveSession(IntID);
tmdg = BuildTmdg(tmdg, TraffMat);
TraffMatView = new DataView(TraffMat);
// Set the data source and bind to the Data Grid control.
tmdg.DataSource = TraffMatView;
tmdg.DataBind();
if (!Panel1.Controls.Contains(tmdg))
{
Panel1.Controls.Add(tmdg);
}
UpdatePanel1.Visible = true;
UpdatePanel1.Update();
}
private DataGrid BuildTmdg(DataGrid dg, DataTable dt)
{
dg.Columns.Clear();
for (int col = 0; col<17; col++)
{
if (col == 0)
{
BoundColumn bc = new BoundColumn
{
HeaderText = " ",
DataField = dt.Columns[col].ToString(),
ReadOnly = true
};
dg.Columns.Add(bc);
}
else
{
ButtonColumn btnc = new ButtonColumn
{
HeaderText = col.ToString(),
ButtonType = ButtonColumnType.PushButton,
DataTextField = dt.Columns[col].ToString(),
CommandName = col.ToString()
};
dg.Columns.Add(btnc);
}
}
return dg;
}
private void Tmdg_ItemCommand(object source, DataGridCommandEventArgs e)
{
Save((Int32)Session["PushIntID"], Convert.ToInt32(e.CommandName), e.Item.DataSetIndex+1);
}
private void Save(int IntID, int col, int row)
{
int newIntID = IntID;
int newcol = col;
int newrow = row;
// Apply changes to DataTable
string newVal = UpdateDataTable(IntID, col, row);
// Apply changes to Database
int rowsAffected = Apply(IntID, col, row, newVal);
// Bind DataTable to TMDG
BindGrid(IntID);
}
private string UpdateDataTable(int IntID, int col, int row)
{
row--;
string val = TraffMat.Rows[row][col].ToString();
if (val == "False")
{
val = "True";
TraffMat.Rows[row][col] = val;
}
else
{
val = "False";
TraffMat.Rows[row][col] = val;
}
TraffMat.AcceptChanges();
SaveSession(IntID);
TraffMatView = new DataView(TraffMat);
return val;
}
private int Apply(int IntID, int col, int row, string NewVal)
{ //redacted, saves values to database
}
protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
{ //redacted, fills DataTable from database, calls SaveSession, calls BindGrid
}
private int GetSession()
{ //redacted, gets session state
}
private void SaveSession(int IntID)
{ //redacted, sets session state
}
}
}
在我看来,当我在 BindGrid() 的两个 "if" 语句中设置断点时,第一个 "if" 经常被跳过,这意味着 Panel1 在那一刻不包含我的数据网格 tmdg及时。这个 "if" 在被忽略的 "first-click" 中被特别跳过。
如果您需要我提供更多信息,请告诉我! 我希望你们中的一个能弄清楚我做错了什么!! 任何和所有评论表示赞赏..
我没有在 Push.aspx.cs 中实例化数据网格 tmdg,而是将其添加到 Push.aspx 并且每次都会触发点击事件。我不确定为什么这在 .aspx 中有效但在 .aspx.cs 文件中无效。
后面有新代码说明...
:::::Push.aspx:::::(此处添加了数据网格)
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Push.aspx.cs" Inherits="TMUWF.Push" MasterPageFile="~/Site.Master" %>
<asp:Content ID="Content3" ContentPlaceHolderID="MainContent" Runat="Server">
<asp:DropDownList ID="DropDownList1"
OnSelectedIndexChanged="DropDownList1_SelectedIndexChanged"
runat="server"
AutoPostBack="True"
AppendDataBoundItems="true"
OnMouseDown="this.size=10;"
OnFocusOut="this.size=1;"
OnDblClick="this.size=1;"
>
</asp:DropDownList>
<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional" OnInit="Panel_Init">
<contenttemplate>
<h3 id="div-Col-Title">Node</h3>
<asp:Panel runat="server" ID="Panel1">
<div id="div-Row-Title"><h3 >Channel</h3></div>
<asp:DataGrid ID="tmdg" CssClass="gvClass push" AutoGenerateColumns="false" runat="server" >
</asp:DataGrid>
</asp:Panel>
</contenttemplate>
</asp:UpdatePanel>
</asp:Content>
:::::Push.aspx.cs:::::(此处删除了数据网格)
//DataGrid tmdg = new DataGrid
//{
// AutoGenerateColumns = false,
// CssClass = "gvClass push"
//};
关于 WHY 的想法表示赞赏。