如何在ASP.NET WebForms中处理来自数据绑定控件的命令?

时间:2012-06-29 13:02:33

标签: asp.net webforms

这个问题看起来很简单,但我找不到答案。我确信我错过了一些东西。

我想使用数据绑定控件(比如一个ListView)和一个在项目模板中执行回发(一个Button)的控件。我希望按钮对此项目中的数据执行某些操作。

代码如下所示:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebFormListCommand.aspx.cs"
    Inherits="TestWebApplication.WebFormListCommand" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:ListView ID="lvTest" runat="server" EnableViewState="false" 
            onitemdatabound="lvTest_ItemDataBound" onitemcommand="lvTest_ItemCommand">
            <ItemTemplate>
                <br />
                <asp:Button ID="btnTest" runat="server" />
            </ItemTemplate>
        </asp:ListView>
    </div>
    </form>
</body>
</html>

代码背后:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace TestWebApplication
{
    public partial class WebFormListCommand : System.Web.UI.Page
    {
        protected void Page_Init(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                lvTest.DataSource = Enumerable.Range(0, 5);
                lvTest.DataBind();
            }
            else
            {
                lvTest.DataSource = Enumerable.Range(5, 5);
                lvTest.DataBind();
            }
        }
        protected void Page_Load(object sender, EventArgs e)
        {

        }

        protected void lvTest_ItemDataBound(object sender, ListViewItemEventArgs e)
        {
            Button button = (Button)e.Item.FindControl("btnTest");
            int value = (int)e.Item.DataItem;
            button.CommandName = "someCommand";
            button.CommandArgument = value.ToString();
            button.Text = value.ToString();
        }


        protected void lvTest_ItemCommand(object sender, ListViewCommandEventArgs e)
        {
            //e.CommandArgument has the new value from the new databinding
        }

    }
}

问题是当按下按钮时,e.CommandArgument具有来自回发数据绑定的值。如果我在回发时没有做数据绑定,则根本不会引发事件。在大多数情况下,这不是问题,因为您将数据绑定到相同的数据。但是,如果一个用户删除例如项目3并且第二个用户决定在同一时间删除项目3,则第二个用户将实际删除第四个项目,因为这些项目将在回发时重新排序。如果启用了ViewState,则可以避免这种情况,但应该可以在没有ViewState的情况下执行命令(在应该避免所有一个地方ViewState之后是数据绑定控件)。为了增加对伤害的侮辱我可以清楚地看到原始(正确)值被发布到服务器。它可以通过Request.Form [“lvTest $ ctrl2 $ btnTest”]检索(键是触发回发的实际控件的UniqueID)

我已经尝试了很多方法将命令应用于正确的项目,例如使用按钮单击而不是使用DataKeys等项目命令,但是我无法获得正确的数据项值。似乎数据绑定控件总是使用行号来获取命令参数,而不是浏览器实际发布的值。我找到的唯一方法是手动查看Request.Form集合,但这似乎不对。当然,我可以通过挂钩JavaScript函数和AJAX调用来解决这个问题,但我想知道如何以纯WebForms方式解决这个问题。我错过了什么?

1 个答案:

答案 0 :(得分:1)

  1. 将代码从Page_Init移至Page_Load

  2. 评论

    lvTest.DataSource = Enumerable.Range(5,5);

    lvTest.DataBind();

  3. 看看它是否有效。

    我还会以声明方式设置CommandName并绑定ComanndArgument属性,而不是将其设置为lvTest_ItemDataBound

    更新:

    1. 不要在回发时重新绑定
    2. ListView
    3. 上启用viewstate

      标记:

      <div>
          <asp:ListView ID="lvTest" runat="server"
              onitemdatabound="lvTest_ItemDataBound" onitemcommand="lvTest_ItemCommand">
              <ItemTemplate>
                  <br />
                  <asp:Button ID="btnTest" runat="server" />
              </ItemTemplate>
          </asp:ListView>
      </div>
      <asp:Label Text="" ID="lblMessage" runat="server" />
      

      C#

          protected void Page_Init(object sender, EventArgs e)
          {
              if (!IsPostBack)
              {
                  lvTest.DataSource = Enumerable.Range(0, 5);
                  lvTest.DataBind();
              }
              else
              {
                  //lvTest.DataSource = Enumerable.Range(5, 5);
                  //lvTest.DataBind();
              }
          }
          protected void Page_Load(object sender, EventArgs e)
          {
      
          }
      
          protected void lvTest_ItemDataBound(object sender, ListViewItemEventArgs e)
          {
              Button button = (Button)e.Item.FindControl("btnTest");
              int value = (int)e.Item.DataItem;
              button.CommandName = "someCommand";
              button.CommandArgument = value.ToString();
              button.Text = value.ToString();
          }
      
      
          protected void lvTest_ItemCommand(object sender, ListViewCommandEventArgs e)
          {
              //e.CommandArgument has the new value from the new databinding
              lblMessage.Text = e.CommandArgument.ToString();
          }