【问题标题】:ASP.NET Web Forms: How to reference CheckBoxList items as 'selected' on a table on another page using only C# and ASP.NET web forms?ASP.NET Web 表单:如何仅使用 C# 和 ASP.NET Web 表单将 CheckBoxList 项目引用为另一个页面上的表上的“已选择”?
【发布时间】:2021-02-20 20:29:11
【问题描述】:

作业说明:

开发一个使用会话对象来存储信息的简单购物车应用程序。您必须创建一个包含两个 Web 表单的 ASP.NET 项目。第一个 Web 表单 ShoppingCart.aspx 允许用户使用一组复选框来选择项目。此页面还显示购物车中的商品数量。

第二个 Web 表单 Display.aspx 在表格中显示所选项目的数量,并允许用户返回到第一个 Web 表单并继续购物。


  • 我正在使用 CheckBoxList 列出我的产品,并在单元格中构建了一个带有 ID 的表格,以接收用户核对的数据。
  • (我考虑过使用 CheckBox 与 CheckBoxList 的想法,但这不是合适的解决方案,也不容易计算所选项目的总数)
  • 我尝试过使用 cookie 和会话状态变量,但不知道如何将它们与表关联。
  • 我可以从标签和文本框中传输测试数据,任何带有 ID 的东西,但不能传输我的 CheckBoxList 项。

在单击列表项上没有唯一 ID 的“结帐”按钮后,如何引用第 1 页上选中的复选框,这将更新第 2 页上所需的表格单元格? p>

示例:如果... 在第 1 页选择了 1lb Dark Roast ... (在下一页上标识为产品 1 的“p001”)

<asp:ListItem Value="15.99">1lb Dark Roast</asp:ListItem>

在第 2 页 (Display.aspx) 上,该产品旁边的“金额”列应更新为“1”

<asp:TableCell ID="p001_amt" runat="server"></asp:TableCell>

如果在第 1 页检查了某项,则结果应该是...(以及其他产品)。

Product Price Amount
1lb dark Roast $15.99 1
1lb Med Roast $15.99 0

1 = 选中,0 = 未选中(作业期望结果显示此表)

任何帮助将不胜感激。谢谢。


这是我的代码中的 sn-ps,如果需要更多,我可以添加指向完整页面的链接。

第 1 页 (ShoppingCart.aspx)

ShoppingCart.aspx
------------------
<asp:Label ID="TotalCart_lbl" runat="server" Text="Total Items in your Cart: "></asp:Label>
<br />
<asp:CheckBoxList ID="Shop_ckbx" runat="server">
                    <asp:ListItem Value="15.99">1lb Dark Roast</asp:ListItem>
                    <asp:ListItem Value="15.99">1lb Medium Roast</asp:ListItem>
                    <asp:ListItem Value="12.99">1lb Decaf Roast</asp:ListItem>
                    <asp:ListItem Value="16.99">1lb Cold Brew</asp:ListItem>
                    <asp:ListItem Value="10.99">1 box Tea</asp:ListItem>
                    <asp:ListItem Value="35.99">French Press</asp:ListItem>
                    <asp:ListItem Value="8.99">CCM Mug</asp:ListItem>
                </asp:CheckBoxList>
<br />
<asp:Button ID="UpdateCart_btn" runat="server" Text="Update Your cart" OnClick="UpdateCart_btn_Click"/>
<br />
<asp:Label ID="Contents_lbl" runat="server" Text="Update To See Cart Contents"></asp:Label>
<br />
<asp:Label ID="Cost_lbl" runat="server" Text="Total: "></asp:Label>
<br />
<asp:Button ID="Checkout_btn" runat="server" PostBackUrl="~/Display.aspx" Text="Go to Checkout" />

ShoppingCart.aspx.cs
---------------------
protected void UpdateCart_btn_Click(object sender, EventArgs e)
      {
         int total = 0; //Total item count

         Contents_lbl.Text = "Your Cart Contains: <br/>- - - - - - - - - - - - - - - -";
         
         foreach (ListItem listItem in Shop_ckbx.Items)
         {
            if (listItem.Selected == true)
            {
               //Add Text to label
               Contents_lbl.Text += "<br/>&#8226 " + listItem.Text;

               //Count Items in Cart
               total += 1;
            }
         }
         Contents_lbl.Text += "<br/>";

         for (int i = 0; i < Shop_ckbx.Items.Count; i++)
         {
            if (Shop_ckbx.Items[i].Selected)
            {
               cost += Convert.ToDouble(Shop_ckbx.Items[i].Value);
               Cost_lbl.Text = "Total: $ " + cost.ToString();
            }
         }
         //Update total items
         TotalCart_lbl.Text = "Total Items in Your Cart: " + total;
      }

protected void Checkout_btn_Click(object sender, EventArgs e)
      {
          How do I reference the items in the checklist on page 1 
          to update the table on page 2 without unique IDs on each list item?
      }


第 2 页代码 (Display.aspx)

Display.aspx
------------------
<asp:Table ID="Display_tbl" runat="server">
                <asp:TableRow runat="server" ID="Header_row" Font-Bold="True" Font-Size="Larger" BackColor="#FFCC99">
                    <asp:TableCell ID="Product_cell" runat="server" Width="250">Product</asp:TableCell>
                    <asp:TableCell ID="Price_cell" runat="server" Width="100">Price</asp:TableCell>
                    <asp:TableCell ID="Amount_cell" runat="server" Width="100">Amount</asp:TableCell>
                </asp:TableRow>
                <asp:TableRow runat="server" ID="p001">
                    <asp:TableCell ID="p001_prod" runat="server">1lb Dark Roast</asp:TableCell>
                    <asp:TableCell ID="p001_price" runat="server">$ 15.99</asp:TableCell>
                    <asp:TableCell ID="p001_amt" runat="server"></asp:TableCell>
                </asp:TableRow>
                <asp:TableRow runat="server" ID="p002" Width="500px">
                    <asp:TableCell ID="p002_prod" runat="server">1lb Med Roast</asp:TableCell>
                    <asp:TableCell ID="p002_price" runat="server">$ 15.99</asp:TableCell>
                    <asp:TableCell ID="p002_amt" runat="server"></asp:TableCell>
                </asp:TableRow>
                <asp:TableRow runat="server" ID="p003">
                    <asp:TableCell ID="p003_prod" runat="server">1lb Decaf</asp:TableCell>
                    <asp:TableCell ID="p003_price" runat="server">$ 12.99</asp:TableCell>
                    <asp:TableCell ID="p003_amt" runat="server"></asp:TableCell>
                </asp:TableRow>
                <asp:TableRow runat="server" ID="p004">
                    <asp:TableCell ID="p004_prod" runat="server">1lb Cold Brew</asp:TableCell>
                    <asp:TableCell ID="p004_price" runat="server">$ 16.99</asp:TableCell>
                    <asp:TableCell ID="p004_amt" runat="server"></asp:TableCell>
                </asp:TableRow>
                <asp:TableRow runat="server" ID="p005">
                    <asp:TableCell ID="p005_prod" runat="server">1 box Tea (50 bags)</asp:TableCell>
                    <asp:TableCell ID="p005_price" runat="server">$ 10.99</asp:TableCell>
                    <asp:TableCell ID="p005_amt" runat="server"></asp:TableCell>
                </asp:TableRow>
                <asp:TableRow runat="server" ID="p006">
                    <asp:TableCell ID="p006_prod" runat="server">French Press</asp:TableCell>
                    <asp:TableCell ID="p006_price" runat="server">$ 35.99</asp:TableCell>
                    <asp:TableCell ID="p006_amt" runat="server"></asp:TableCell>
                </asp:TableRow>
                <asp:TableRow runat="server" ID="p007">
                    <asp:TableCell ID="p007_prod" runat="server">CCM Coffee Mug</asp:TableCell>
                    <asp:TableCell ID="p007_price" runat="server">$ 8.99</asp:TableCell>
                    <asp:TableCell ID="p007_amt" runat="server"></asp:TableCell>
                </asp:TableRow>
                <asp:TableRow runat="server" ID="Total_row">
                    <asp:TableCell ID="Total_prod" runat="server">Total</asp:TableCell>
                    <asp:TableCell ID="Total_price" runat="server"></asp:TableCell>
                    <asp:TableCell ID="Total_amt" runat="server"></asp:TableCell>
                </asp:TableRow>
            </asp:Table>
            
<asp:LinkButton ID="Back_linkbtn" runat="server" OnClick="Back_linkbtn_Click">Go Back to the Shop</asp:LinkButton>


Display.aspx.cs
-------------------
protected void Page_Load(object sender, EventArgs e)
      {
         ShoppingCart prevPage = PreviousPage as ShoppingCart;
         if (prevPage != null) 
         {
              NOT SURE HOW TO LINK TO MY CHECKLIST ITEMS 
              TO UPDATE 'AMOUNT' TABLE CELLS
              
              Also,
              CHECKBOXES ON PREVIOUS PAGE NEED TO STAY SELECTED 
              in order to CONTINUE SHOPPING.
              
         } 
      }

protected void Back_linkbtn_Click(object sender, EventArgs e)
      {
         Response.Redirect("ShoppingCart.aspx");
      }


【问题讨论】:

    标签: c# asp.net webforms


    【解决方案1】:

    好的,所以我们这里的问题当然是匹配您在一个页面上选择的“事物”,然后在下一个网页上解决这个问题。

    公平地说,这里的问题是毫无疑问您必须“弥补”这里的数据。这真的会伤害整个过程,因为您必须输入两次数据(一次在此页面上,然后在目标页面上)。更糟糕的是,您必须通过“文本”进行匹配。一点点空间、句号等,你的整个系统就会崩溃。

    我建议我们不要担心,也不必匹配这些值。我们可以一次性解决一个巨大的问题,还可以减少标记、代码和你所有的生活麻烦(好吧,好吧,只是编码部分 - 不能解决所有问题!!!)。

    因此,我建议我们创建一个表格并将其用于两个页面,而不是复选框“列表”。这样不仅可以让我们远离带有软垫墙的房间,而且我们可以处理您选择的“一排”东西,而不是对拼写甚至我们在该排中放置的内容一无所知。通过这样做,您几乎无需更改代码即可将“列表”从我们的表更改为数据库 - 整个 she-bang 都可以工作!!

    所以,让我们使用(创建)一个表,这不仅简单,而且我认为设置我们的数据要干净得多。

    所以,我们将在页面的开头有这个(一个表格和整个页面类的一些总值。

    public class MyFirstOrderPage : System.Web.UI.Page
    {
    private DataTable MyTable = new DataTable();
    
    private decimal MyTotal = 0;
    private int MyTotalQty = 0;
    

    好的,现在让我们在此页面中执行 sub 来加载上表。

    public void CreateData()
    {
        MyTable.Columns.Add("Product", typeof(string));
        MyTable.Columns.Add("Price", typeof(decimal));
        MyTable.Columns.Add("Qty", typeof(int));
        MyTable.Columns.Add("Amount", typeof(decimal));
        MyTable.Columns.Add("Purchased", typeof(bool));
    
        MyTable.Rows.Add({"11b Dark Roast",15.99,1,0,false});
        MyTable.Rows.Add({"11b Medium Roast",15.99,1,0,false});
        MyTable.Rows.Add({"1b Decaf Roast",12.99,1,0,false});
        MyTable.Rows.Add({"11b Cold Brew",16.99,1,0,false});
        MyTable.Rows.Add({"1 box Tea Brew",10.99,1,0,false});
        MyTable.Rows.Add({"French Press",35.99,1,0,false});
        MyTable.Rows.Add({"CCM Mug",8.99,1,0,false});
    }
    

    现在您不仅可以“轻松”阅读上述内容,还可以更改/查看并查看列,然后数据随之而来 - 因此您可以看到我们决定为购买的商品设置数量和列。这将节省BUCKETS代码和BUCKETS标记。我们可以将上面的内容用于两个页面 - 不必拥有此列表的两个副本!!!!

    好的,现在我们有桌子了。接下来,让我们显示该表。我们可以在订单页面中使用与结帐页面中非常相似的网格(节省更多时间、更多代码甚至更多标记!!!)。

    所以,让我们使用网格视图。我们可以使用列表视图,如果您想要一张可爱的图片和更多的产品描述,我会考虑。但是,gridview 很好。

    所以,这里是 gridview 的标记:

    <form id="form1" runat="server">
        <div>
            <asp:GridView ID="GridView1" runat="server" ShowFooter="true"
                Font-Bold="True" Font-Size="Larger" BackColor="#FFCC99" AutoGenerateColumns="False">
    
                <Columns>
                    <asp:BoundField DataField="Product" HeaderText="Product" Headerstyle-width="250px" />
                    <asp:BoundField DataField="Price" DataFormatString="{0:C2}" HeaderText="Price" Headerstyle-width="80px" />
                    <asp:TemplateField HeaderText="Qty" >
                        <ItemTemplate>
                        <asp:TextBox ID="Qty" runat="server" Width="60px" 
                            Text ='<%# Eval("Qty") %>' 
                            MyRow = '<%# Container.DataItemIndex %>' 
                            AutoPostBack="true" OnTextChanged="Qty_TextChanged"
                          />
                        </ItemTemplate>
                </asp:TemplateField>
    
                <asp:TemplateField HeaderText="Amount">
                    <ItemTemplate>
                        <asp:TextBox ID="Amount" runat="server" width="80px"
                            Text ='<%# FormatCurrency(Eval("Qty") * Eval("Price")) %>' Enabled="false" DataFormatString="{0:C2}"  />
                    </ItemTemplate>
                </asp:TemplateField>
    
                <asp:TemplateField HeaderText="Purchase"  ItemStyle-HorizontalAlign="Center">
                    <ItemTemplate >
                        <asp:CheckBox ID="CheckBox1" runat="server" width="110px" 
                            Checked ='<%# Eval("Purchased") %>' 
                            MyRow = '<%# Container.DataItemIndex %>' 
                            AutoPostBack="true" 
                            OnCheckedChanged="CheckBox1_CheckedChanged1"
                            />
                    </ItemTemplate>
                </asp:TemplateField>
    
                </Columns>
    
                <FooterStyle BackColor="#990000" Font-Bold="True" ForeColor="White" />
            </asp:GridView>
            <asp:HiddenField ID="qtycheck" runat="server" ClientIDMode="Static" />
    
            <br />
            <asp:Button ID="Checkout_btn" runat="server"  Text="Proceed to Checkout"
                style="width:140px;height:60px;background-color:#FFCC99;border-radius:25px"
                OnClientClick="hasorder();return false;"/>
            <script>
                function hasorder() {
                    var CheckQty = document.getElementById("qtycheck")
                    if (CheckQty.value > 0) {
                        window.location.href = "/CheckOut.aspx"
                    }
                    else {
                        alert("Please select at least one Purchase before proceding to check out");
                        return false;
                    }
                }
            </script>
    

    现在这是一个标记,但它仍然比你的第二页表少得多,你更好地看到我们的第二页现在是非常少的标记!

    好的,我们有了上面的内容。唯一真正的问题是,当您选中一个框时,我们需要汇总所有内容。当您编辑或更改数量时,同样的事情 - 更新总数。

    因此,我们为每个部分拥有的代码又是相当有限的。我会一口气发完:

    protected void Page_Load(object sender, System.EventArgs e)
    {
        if (System.Web.UI.Page.IsPostBack == false)
        {
            // ok first page load, now check if reutrn from checkout 
            if (System.Web.UI.Page.Session["MyTable"] == null)
            {
                CreateData(); // first time here  - create the data
                System.Web.UI.Page.Session["MyTable"] = MyTable;    // save the data table
            }
            else
                // we have data - (so this is user change of mind from checkout page)
                MyTable = System.Web.UI.Page.Session["MyTable"];
    
            // ok, now load our data into the grid
            LoadData(); // load the data
        }
        else
    
            // this is a post back due to general changes and selections for this
            // page under normal and mutliple operations and choices by the user.
    
            // we dont' need to re-display the grid - it persists automatic
            // however the datatable variable does NOT persist - so get from session
            MyTable = System.Web.UI.Page.Session["MyTable"];
    }
    
    public void LoadData()
    {
        MyTotal = 0;
        MyTotalQty = 0;
        qtycheck.Value = 0;
        GridView1.DataSource = MyTable;
        GridView1.DataBind();
    }
    
    protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
    {
        if (e.Row.RowType == DataControlRowType.DataRow)
        {
            TextBox MyAmount = e.Row.FindControl("Amount");
            DataRow MyRow = MyTable.Rows(e.Row.RowIndex);
    
            MyRow("Amount") = MyRow("Qty") * MyRow("Price");
    
            if (MyRow("Purchased") == true)
            {
                // total up the qty purcchased and the amount
                MyTotal += MyRow("Amount");
                MyTotalQty += MyRow("Qty");
            }
        }
        else if (e.Row.RowType == DataControlRowType.Footer)
        {
            // this is our bottom last footer. 
            e.Row.Cells(3).Text = Strings.FormatCurrency(MyTotal);
            e.Row.Cells(2).Text = MyTotalQty;
            e.Row.Cells(1).Text = "Totals:";
    
            qtycheck.Value = MyTotalQty;     // a hidden control - to check for qty > 0 on checkout
        }
    }
    
    protected void CheckBox1_CheckedChanged1(object sender, EventArgs e)
    {
    
        // user click on purchase a row - udpate totals.
        CheckBox cBox = sender;
        int RowID = cBox.Attributes("MyRow");
        MyTable.Rows(RowID).Item("Purchased") = cBox.Checked;
    
        // data table has been changed - so we call the load data routine to udpate 
        // our grid
        LoadData();
    }
    
    protected void Qty_TextChanged(object sender, EventArgs e)
    {
    
        // user changed the qry in a row
        TextBox tBox = sender;
        int RowID = tBox.Attributes("MyRow");
        MyTable.Rows(RowID).Item("Qty") = tBox.Text;
    
        // data table has been changed - so we call the load data routine to udpate 
        // our grid
        LoadData();
    }
    }
    

    现在这是“一点”代码,但同样,不是很多。

    所以,你现在在运行后得到这个:

    所以,请注意当您选中一个框时我们会做什么!

    我们这样做很简单:

    protected void CheckBox1_CheckedChanged1(object sender, EventArgs e)
    {
    
        // user click on purchase a row - udpate totals.
        CheckBox cBox = sender;
        int RowID = cBox.Attributes("MyRow");
        MyTable.Rows(RowID).Item("Purchased") = cBox.Checked;
    
        // data table has been changed - so we call the load data routine to udpate 
        // our grid
        LoadData();
    }
    

    所以,现在真的不存在匹配问题,是吗?您单击一行,我们只需更改已购买设置(真/假标志)。就是这样 - 完成了!无需匹配。当您因此选中一个框时,我们更改表值,然后简单地对代码说请您重新显示数据!所以现在我们正在保存所有匹配的工作!!!

    现在,结帐代码变成了公园散步。

    当您点击按钮结帐时,我们跳转到结帐页面。

    标记现在非常简单 - 因为它与第一页非常相似 - 但无法更改内容。因此:

    <asp:GridView ID="GridView2" runat="server" ShowFooter="true"
                Font-Bold="True" Font-Size="Larger" BackColor="#FFCC99" 
                 AutoGenerateColumns="False" 
             >
    
         <Columns>
           <asp:BoundField DataField="Product" HeaderText="Product" Headerstyle-width="250px" />
           <asp:BoundField DataField="Price" DataFormatString="{0:C2}" HeaderText="Price" Headerstyle-width="80px" />
           <asp:BoundField DataField="Qty"  HeaderText="Qty" Headerstyle-width="80px" />
           <asp:BoundField DataField="Amount"  HeaderText="Amount" Headerstyle-width="80px" />
         </Columns>
       <FooterStyle BackColor="#990000" Font-Bold="True" ForeColor="White" />
    
      </asp:GridView>
    
            <br />
            <asp:Button ID="ChangeOrder_btn" runat="server" PostBackUrl="~/SimpleButton.aspx" Text="Change order"
               style="width:140px;height:60px;background-color:#FFCC99;border-radius:25px"
                  />
            <br />
        </div>
    

    页面看起来像:

    所以,您现在明白我们为什么使用表了 - 因为现在 SAME 数据驱动两个页面,我们的问题变得越来越小 - 而不是越来越大!

    我们的结帐页面代码是这样的:

    class CheckOut : System.Web.UI.Page
    {
    private decimal MyTotal = 0;
    private int MyTotalQty = 0;
    
    protected void Page_Load(object sender, System.EventArgs e)
    {
        DataTable MyTable = System.Web.UI.Page.Session["MyTable"];
        DataView dv = new DataView(MyTable); // we use data view in palce of data table - it can fitler!!
    
        dv.RowFilter = "Purchased = True";
    
        GridView2.DataSource = dv;
        GridView2.DataBind();
    }
    
    protected void GridView2_RowDataBound(object sender, GridViewRowEventArgs e)
    {
        if (e.Row.RowType == DataControlRowType.DataRow)
        {
            MyTotal += e.Row.Cells(3).Text;
            MyTotalQty += e.Row.Cells(2).Text;
        }
        else if (e.Row.RowType == DataControlRowType.Footer)
        {
            e.Row.Cells(3).Text = Strings.FormatCurrency(MyTotal);
            e.Row.Cells(2).Text = MyTotalQty;
            e.Row.Cells(1).Text = "Totals:";
        }
    }
    }
    

    因此,通过在第一页上构建更好的设计和鼠标陷阱以及更好的方法,下一页变得非常简单,因为我们重用数据,重用表格,实际上接近 re - 也使用了网格!!!

    要显示订单,我们只需要获取表格,并按购买的方式过滤结果。

    返回并改变主意的按钮呢?好吧,它只是跳回到那个订单页面。

    因此,虽然我们确实必须在第一页中建立更多“标记”,但我们在第二页中大量减少了标记。

    【讨论】:

    • 你不知道我是多么感激这么多的帮助。这很有意义。不幸的是,我的“教授”认为回答问题是工作的可选部分,所以我没有人可以问,而且我认识的人也没有使用 ASP.NET。你真是一个了不起的人。尽管它与我给出的示例不完全相同,但这确实好多了,并且 100% 更有意义。我已经为此拉了一个星期的头发!谢谢你UUUU
    • 太棒了!我想一个带有“表格”的例子会好得多。我的意思是有一百万种方法可以做这些事情。为您的第一个列表使用标记的问题在于,您在第二页上重新生成了一个列表,您必须重新输入,并且所有内容都必须 100% 匹配 - (非常困难)。如果您想说播放并添加更多行,那么您将再次在两个页面中编辑标记 - 很容易让设置失败。虽然我们的标记少了很多,但我们确实在第一页有更多的代码,但结果是第二页变成了部分。
    猜你喜欢
    • 2012-08-30
    • 2014-07-07
    • 1970-01-01
    • 2021-12-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-28
    • 2023-04-11
    相关资源
    最近更新 更多