在 asp .net / c# 中创建可以访问动态文本框并记住它们以前的值的动态按钮的更好方法?

发布于 2024-12-26 04:36:00 字数 2353 浏览 1 评论 0 原文

事情是这样的,我现在有了一个我想要的工作原型,它似乎非常适合我想要做的事情。话虽如此,这可能不是最好的方法。我所说的“最好”既指程序的简单性,也指我实际编码的方式。无论如何,首先描述页面应该做什么:

1)页面包含一个文本框(Textbox1),一个占位符(Placeholder1)和一个按钮(Button1),

代码很简单:

<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>

<asp:Button ID="Button1" runat="server" Text="Button" onclick="Button1_Click" />

<hr />
<asp:PlaceHolder ID="PlaceHolder1" runat="server"></asp:PlaceHolder>
<hr />

2)用户可以将数字放入文本框(假设是 99)并单击按钮。然后,占位符将填充 99 个文本框,每个文本框旁边都有一个“保存”按钮 3)用户可以编辑任何文本框并单击其旁边的“保存”,然后由按钮单击事件调用的函数需要能够访问 A)文本框当前值,B)文本框旧值,C) 这里的任何数量的元数据

都是我当前的工作解决方案:

    protected void Page_Load(object sender, EventArgs e)
    {
        createStuff(false);

    }

    void test(object sender, EventArgs e)
    {
        Button btn = (Button)sender;
        Response.Write(btn.ID + "Clicked" + "<br />");
        Response.Write("Metadata: " + Session[btn.ID + "a"] + "<br />");
        Response.Write("Old text: " + Session[btn.ID + "b"] + "<br />");

        TextBox txtBlah = (TextBox)PlaceHolder1.FindControl("txt"+btn.ID);
        Response.Write("New text: " + txtBlah.Text + "<br />");

        Session[btn.ID + "b"] = txtBlah.Text;

    }

    protected void Button1_Click(object sender, EventArgs e)
    {
        Session["num"] = TextBox1.Text;
        createStuff(true);
    }

    private void createStuff(bool btnClick)
    {
        PlaceHolder1.Controls.Clear();

        int numBtn = Convert.ToInt32(Session["num"]);

        for (int i = 0; i < numBtn; i++)
        {
            TextBox txtTemp = new TextBox();
            txtTemp.Text = "old" + i;
            txtTemp.ID = "txt" + "btn" + i;
            PlaceHolder1.Controls.Add(txtTemp);

            Button btn = new Button();
            btn.Text = "btn" + i;
            btn.ID = "btn" + i;
            btn.Click += new EventHandler(test);
            PlaceHolder1.Controls.Add(btn);

            Session[btn.ID + "a"] = "meta" + i;

            if (btnClick)
            {
            Session[btn.ID + "b"] = txtTemp.Text;
            }

            PlaceHolder1.Controls.Add(new LiteralControl("<br />"));
        }


    }

我认为这实际上相当不错,我对此非常满意。但是,我知道我必须做出一些改进,因为一些关于 ASP 回发系统和对象模型或其名称的教程现在仍然让我有些困惑。

任何帮助甚至只是想法都有帮助,谢谢。

Here's the thing, I now have a working prototype of what I want and it seems to work perfectly for what I want to do. With that said, this cannot POSSIBLY be the best way to do it. And by best I mean both in terms of program simplicity but also HOW i actually coded it. Anyways first a description of what the page should do:

1) the page contains a textbox (Textbox1), a placeholder (Placeholder1), and a button (Button1)

the code for this is simple:

<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>

<asp:Button ID="Button1" runat="server" Text="Button" onclick="Button1_Click" />

<hr />
<asp:PlaceHolder ID="PlaceHolder1" runat="server"></asp:PlaceHolder>
<hr />

2) the user can put a number into the textbox (lets say 99) and click the button. the placeholder will then be filled with 99 textboxes with a "save" button next to each one
3)the user can edit any textbox and click save next to it and the function that is then called by the button click event needs to be able to have access to A) the textboxes current value, B) the textboxes old value, C) any amount of meta data

here is my current working solution:

    protected void Page_Load(object sender, EventArgs e)
    {
        createStuff(false);

    }

    void test(object sender, EventArgs e)
    {
        Button btn = (Button)sender;
        Response.Write(btn.ID + "Clicked" + "<br />");
        Response.Write("Metadata: " + Session[btn.ID + "a"] + "<br />");
        Response.Write("Old text: " + Session[btn.ID + "b"] + "<br />");

        TextBox txtBlah = (TextBox)PlaceHolder1.FindControl("txt"+btn.ID);
        Response.Write("New text: " + txtBlah.Text + "<br />");

        Session[btn.ID + "b"] = txtBlah.Text;

    }

    protected void Button1_Click(object sender, EventArgs e)
    {
        Session["num"] = TextBox1.Text;
        createStuff(true);
    }

    private void createStuff(bool btnClick)
    {
        PlaceHolder1.Controls.Clear();

        int numBtn = Convert.ToInt32(Session["num"]);

        for (int i = 0; i < numBtn; i++)
        {
            TextBox txtTemp = new TextBox();
            txtTemp.Text = "old" + i;
            txtTemp.ID = "txt" + "btn" + i;
            PlaceHolder1.Controls.Add(txtTemp);

            Button btn = new Button();
            btn.Text = "btn" + i;
            btn.ID = "btn" + i;
            btn.Click += new EventHandler(test);
            PlaceHolder1.Controls.Add(btn);

            Session[btn.ID + "a"] = "meta" + i;

            if (btnClick)
            {
            Session[btn.ID + "b"] = txtTemp.Text;
            }

            PlaceHolder1.Controls.Add(new LiteralControl("<br />"));
        }


    }

I think this is actually pretty decent and I am very happy with it. But, I know there have to be some improvements i can make since some of the tutorials on how the ASP postback system and object model or whatever its called are even now confusing me some.

any help or even just ideas are helpful thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

东走西顾 2025-01-02 04:36:00

我能看到的唯一主要改进是:使用 UserControl ,将 TextBoxButton 放入其中,添加属性(例如 OldValue/NewValue,存储在 ViewState/TextBox 中)并将这些 UserControl 添加到使用 PlaceHolder ="nofollow noreferrer">加载控件

“元数据”也应该作为属性存储在用户控件中。您应该使用事件在用户控件和页面之间进行通信(fe TextSaved)。

您可以将创建的控件数量存储在 ViewState 中而不是 Session 中。这是您需要在页面中存储的唯一内容。将 UserControl 的索引附加到它的 ID 中。


Web 用户控件的一般优点:

Web 用户控件的最大优点是它们可以创建为站点模板并在整个站点中使用。例如,它们可以包含站点的菜单/链接结构,并且可以在所有其他 aspx 页面上使用。

这意味着:

  • 如果网站在当前布局/结构中引入了新的站点范围链接,那么我们将其放在用户控件上一次就足够了。如果使用了Web用户控件,所有页面都会更新一次。
  • 如果有需要更正的链接,可以在服务器端一次完成。
  • .ascx 文件可以用作纯 HTML 的简单替代品,也可以用于响应事件:这意味着甚至可以针对它们创建自定义代码并将其放入文件后面的代码中。

  • http://www.dotnet-guide.com/usercontrol5.html

用户控件封装了复杂性是什么增加

......并减少错误的可能性

总是好的阅读这个 SO-answer 了解更多示例。

The only major improvement i can see is: use a UserControl, put the TextBox and Button inside, add properties (like OldValue/NewValue, stored in ViewState/TextBox) and add these UserControls to the PlaceHolder after you've created instances by using LoadControl.

The "MetaData" should also be stored as property in the UserControl. You should use Events to communicate between the UserControl and Page(f.e. TextSaved).

You can store the number of created controls in ViewState instead of the Session. That's the only thing you need to store in the Page. Append the index of the UserControl to it's ID.


General advantages of a Web User Control:

The biggest advantage of the Web User controls is that they can be created as a site template and used through out the site. For example they can be made to contain the Menu/Link structure of a site and can be used at all the other aspx pages.

This means the following :

  • If the website introduces a new site-wide link within the current layout/structure, it is enough if we put it on the user control once. All pages will be updated once if the web user control is used in them.
  • If there is any link to be corrected, it can be done once at the server side.
  • The .ascx files can either be used as a simple alternative to the plain HTML or they can also be used to respond to events: This means even custom code can be created against them and put in the code behind files.

  • http://www.dotnet-guide.com/usercontrol5.html

UserControls encapsulate complexity what is always good to increase

  • Reusability
  • Readability
  • Maintainability
  • Extensibility

... and to reduce the possibility of errors

Read this SO-answer for more examples.

山人契 2025-01-02 04:36:00

好吧,我不知道这是否是我发回最新代码的正确位置,但我想它会被视为“答案”。我还想说非常感谢您的回答,它们非常有帮助。有点神秘,但后来有五十页左右的教程,是的,你的推荐非常棒,所以谢谢你,太棒了。无论如何,这是我最新的一个,它与我认为您推荐的添加内容完美配合。如果您想达到峰值,看看您是否仍然会做一些稍微不同的事情,或者可能以更简单的方式,请随时让我知道

我的用户控件“MyControl”

ascx:

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="MyControl.ascx.cs" Inherits="DBtest.MyControl" %>
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<asp:Button ID="Button1" runat="server" Text="Button" onclick="Button1_Click" />
<br />

ascx.cs:

    //private String _oldText;
    private String _metaData;

    public String OldText
    {
        get
        {
            //return _oldText;
            return (String)ViewState["OldText"];
        }
        set
        {
            //_oldText = value;
            ViewState["OldText"] = value;
        }
    }

    public String MetaData
    {
        get
        {
            return _metaData;
        }
        set
        {
            _metaData = value;
        }
    }

    public String NewText
    {
        get
        {
            return TextBox1.Text;
        }
        set
        {
            TextBox1.Text = value;
        }
    }

    protected void Page_Load(object sender, EventArgs e)
    {

    }

    protected void Button1_Click(object sender, EventArgs e)
    {
        Response.Write("My ID: " + this.ID + "<br />");
        Response.Write("My Metadata: " + _metaData + "<br />");
        Response.Write("My Old Text: " + ViewState["OldText"] + "<br />");
        Response.Write("My New Text: " + TextBox1.Text + "<br />");

        ViewState["OldText"] = TextBox1.Text;
    }

然后是我的页面,aspx:

<%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="TESTdynamicButton3.aspx.cs" Inherits="DBtest.TESTdynamicButton3" %>
<%@ Register TagPrefix="uc" TagName="Spinner" Src="MyControl.ascx" %>

<asp:Content ID="Content1" ContentPlaceHolderID="HeadContent" runat="server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

    <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>

    <asp:Button ID="Button1" runat="server" Text="Button" onclick="Button1_Click" />

    <hr />
    <asp:PlaceHolder ID="PlaceHolder1" runat="server"></asp:PlaceHolder>
    <hr />

</asp:Content>

aspx .cs:

    protected void Page_Load(object sender, EventArgs e)
    {
        createStuff(false);
    }

    protected void Button1_Click(object sender, EventArgs e)
    {
        ViewState["num"] = TextBox1.Text;
        createStuff(true);
    }

    private void createStuff(bool btnClick)
    {
        PlaceHolder1.Controls.Clear();
        int numBtn = Convert.ToInt32(ViewState["num"]);

        for (int i = 0; i < numBtn; i++)
        {
            MyControl temp2 = LoadControl("MyControl.ascx") as MyControl;
            temp2.ID = "uc" + i;
            temp2.MetaData = "meta" + i;
            //not sure why this DOES work, i would think it is overwritten each page load >.<
            temp2.OldText = "old" + i;

            if (btnClick)
            {
                temp2.NewText = "old" + i;
                //not sure why this doesnt work below this line
                //temp2.OldText = "old" + i;
            }

            //also not sure why this won't work
            //temp2.OldText = temp2.NewText;

            PlaceHolder1.Controls.Add(temp2);
        }
    }

我还有一些内容,我不确定为什么或不使用这些行来让“旧文本”视图状态最初正确填充。我本以为我需要进行按钮单击检查,并且只在第一次设置视图状态才能使其正常工作。我也不确定我明白为什么当我尝试将 createStuff() 函数移动到 OnInit 或覆盖预初始化函数时它不起作用..

谢谢!

狮子座

ok i dunno if this is the right place for me to post back my newest code but i guess it would count as an "answer". also I want to say thank you so much for your answers they have been incredibly helpful. a little cryptic but fifty pages of tutorials or so later and yes your recomendations were fantastic so thank you and bravo. anyways heres my newest one that works perfectly with what I think are your recomended additions. if you want to take a peak and see if youd still do anything a little different or maybe in an easier way please feel free to let me know

first my user control "MyControl"

ascx:

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="MyControl.ascx.cs" Inherits="DBtest.MyControl" %>
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<asp:Button ID="Button1" runat="server" Text="Button" onclick="Button1_Click" />
<br />

ascx.cs:

    //private String _oldText;
    private String _metaData;

    public String OldText
    {
        get
        {
            //return _oldText;
            return (String)ViewState["OldText"];
        }
        set
        {
            //_oldText = value;
            ViewState["OldText"] = value;
        }
    }

    public String MetaData
    {
        get
        {
            return _metaData;
        }
        set
        {
            _metaData = value;
        }
    }

    public String NewText
    {
        get
        {
            return TextBox1.Text;
        }
        set
        {
            TextBox1.Text = value;
        }
    }

    protected void Page_Load(object sender, EventArgs e)
    {

    }

    protected void Button1_Click(object sender, EventArgs e)
    {
        Response.Write("My ID: " + this.ID + "<br />");
        Response.Write("My Metadata: " + _metaData + "<br />");
        Response.Write("My Old Text: " + ViewState["OldText"] + "<br />");
        Response.Write("My New Text: " + TextBox1.Text + "<br />");

        ViewState["OldText"] = TextBox1.Text;
    }

then my page, aspx:

<%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="TESTdynamicButton3.aspx.cs" Inherits="DBtest.TESTdynamicButton3" %>
<%@ Register TagPrefix="uc" TagName="Spinner" Src="MyControl.ascx" %>

<asp:Content ID="Content1" ContentPlaceHolderID="HeadContent" runat="server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

    <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>

    <asp:Button ID="Button1" runat="server" Text="Button" onclick="Button1_Click" />

    <hr />
    <asp:PlaceHolder ID="PlaceHolder1" runat="server"></asp:PlaceHolder>
    <hr />

</asp:Content>

aspx.cs:

    protected void Page_Load(object sender, EventArgs e)
    {
        createStuff(false);
    }

    protected void Button1_Click(object sender, EventArgs e)
    {
        ViewState["num"] = TextBox1.Text;
        createStuff(true);
    }

    private void createStuff(bool btnClick)
    {
        PlaceHolder1.Controls.Clear();
        int numBtn = Convert.ToInt32(ViewState["num"]);

        for (int i = 0; i < numBtn; i++)
        {
            MyControl temp2 = LoadControl("MyControl.ascx") as MyControl;
            temp2.ID = "uc" + i;
            temp2.MetaData = "meta" + i;
            //not sure why this DOES work, i would think it is overwritten each page load >.<
            temp2.OldText = "old" + i;

            if (btnClick)
            {
                temp2.NewText = "old" + i;
                //not sure why this doesnt work below this line
                //temp2.OldText = "old" + i;
            }

            //also not sure why this won't work
            //temp2.OldText = temp2.NewText;

            PlaceHolder1.Controls.Add(temp2);
        }
    }

and i also have a couple contents where im not sure it makes perfect sense why or do or dont use these lines to get the "old text" viewstate to populate properly initially. i would have thought i need to have that buttonclick check and only set the viewstate that first time to get it to work. also im not sure i understand why when i tried moving the createStuff() function to OnInit or the pre init functions overridden it wouldnt work..

thanks!

Leo

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文