【问题标题】:Reading values from dynamically created TextBox ASP.NET (Within table)从动态创建的 TextBox ASP.NET(表内)读取值
【发布时间】:2014-05-13 11:18:55
【问题描述】:

所以我有一个List<SettingsValue>,我将用它来填充<table runat="server"> (System.Web.UI.HtmlControls.HtmlTable)。

问题在于,当提交表单时,会使用初始值重新创建字段。然后当我遍历元素时,它们都没有改变。但如果我不重新创建它们,那么检查输入值的代码甚至找不到控件。

我不想通过查询字符串发布数据

我通过调用带有参数“id”的方法GetSettingsFromDatabase 来接收设置。 Id 是具有设置的“应用程序”的键。在页面上有一个组合框,用户可以在其中选择他们希望更改设置的应用程序。当在组合框中选择一个项目时,会发生回发,然后我希望再次调用 LoadSettings()。


HTML - 行:

<tr align="left" valign="top" runat="server">
    <th runat="server">
        <asp:Label runat="server" Text="{field.Name}" />
    </th>
    <td runat="server">
        <asp:TextBox ID="txt{field.ID}_{field.Name}" runat="server" Text="{value}" />
    </td>
</tr>


C# - 模型:

public class SettingsValue
{
    public long ID { get; set; }
    public long FieldID { get; set; }
    public string Value { get; set; }
    public string RelatedID { get; set; }

    public SettingsField Field { get; set; }
}

public class SettingsField
{
    public long ID { get; set; }
    public long CategoryID { get; set; }
    public string Name { get; set; }
    public string DataType { get; set; }
    public bool Required { get; set; }
    public bool Visible { get; set; }

    public SettingsCategory Category { get; set; }
}

public class SettingsCategory
{
    public SettingsCategory()
    {
        Fields = new List<SettingsField>();
    }

    public long ID { get; set; }
    public string Name { get; set; }
    public string Provider { get; set; }
    public SettingsCategoryType Type { get; set; }

    public List<SettingsField> Fields { get; private set; }
}


C# - 行生成:

private void LoadSettings(long id)
{
    // The id represents some application that has settings

    List<SettingsValue> setting = new List<SettingsValue>();
    if (id > 0)
        settings = GetSettingsFromDatabase(id);

    RenderSettings(settings);
}

private void RenderSettings(List<SettingsValue> settings)
{
    table.Rows.Clear();

    foreach (var value in settings)
    {
        var field = value.Field;
        var fieldGUI_ID = string.Format("{0}_{1}", field.ID, field.Name);

        var row = new HtmlTableRow();
        row.Attributes.Add("runat", "server");
        row.Align = "left";
        row.VAlign = "top";

        var th = new HtmlTableCell("th");
        th.Attributes.Add("runat", "server");

        var td = new HtmlTableCell("td");
        td.Attributes.Add("runat", "server");

        var input = new TextBox();
        input.ID = "txt" + fieldGUI_ID;
        input.Text = value.Value;
        input.Width = new Unit("305px");
        input.Attributes.Add("runat", "server");

        var label = new Label();
        label.Text = field.Name;
        label.Attributes.Add("for", input.ClientID);


        th.Controls.Add(label);
        row.Cells.Add(th);

        td.Controls.Add(input);
        row.Cells.Add(td);

        table.Rows.Add(row);
    }
}


C# - 页面加载

protected void Page_Load( object sender, EventArgs e )
{
    if (!Page.IsPostBack )
    {
        LoadSettings(-1);
    }
}


C# - 提交时

我们使用 ComponentArt 库进行回调 &lt;ComponentArt:Callback ID="callSettings" runat="server" OnCallback="callSettings_OnCallback" /&gt;,但它与常规 ASP.NET 并没有什么不同。

protected void callSettings_OnCallback( object sender, ComponentArt.Web.UI.CallBackEventArgs e )
{
    long id = 421;
    List<SettingsValue> settings = GetSettingsFromDatabase(id);

    List<SettingsValue> updatedValues = new List<SettingsValue>();
    foreach (SettingsField f in fields)
    {
        var val = GetSettingValueFromInput(f);
        if (val != null)
            updatedValues.Add(val);
    }

    UpdateSettingsToDatabase(updatedValues);
}

private SettingsValue GetSettingValueFromInput(SettingsField field)
{
    var fieldGUI_ID = "txt" + string.Format("{0}_{1}", field.ID, field.Name);
    var res = settings.Single(x => x.FieldID == field.ID);

    foreach (HtmlTableRow row in table.Rows)
    {
        foreach (HtmlTableCell cell in row.Cells)
        {
            var ctrl = cell.FindControl(fieldGUI_ID);
            var input = ctrl as TextBox;
            if (ctrl == null || input == null)
                continue;

            res.Value = input.Text;
            return res;
        }
    }
    return res;
}

我查看了其他几个问题,但还没有解决。

【问题讨论】:

  • 为什么不将其存储在Session 中,而不是通过ViewState 全部发布给客户端?或者更好的是,使用GridView 或其他呈现为表格的数据绑定Web 控件,自动将可变信息存储在ViewState 中?
  • 我无法更改页面的任何布局或重大更改
  • @TimSchmelter 我应该在Session 中存储什么?
  • @LazyTarget 你的问题和may的问题很相似,能不能请你阅读THIS并在那里发表你的想法?
  • 也许This 会有用。

标签: c# asp.net viewstate dynamically-generated


【解决方案1】:

当您动态创建控件时,您必须仅在第一次初始化该值。像这样的,

PageLoad() {
    var txtBox = new TextBox();
    this.Controls.Add(txtBox);
    if (!this.IsPostBack) {
        txtBox.Text = "this is initial value";
    }
}

现在你可以看到初始值只会在页面第一次加载时设置(没有回发)。下次页面回传时,控件会重新创建,值会由页面自动设置。

对于动态控件,您必须在每次加载页面时创建和添加控件(无论是回发还是非回发)。但是您不必每次都设置初始值。只有在第一次加载 Page 时才设置初始值。

【讨论】:

    猜你喜欢
    • 2013-05-13
    • 2016-08-30
    • 1970-01-01
    • 2018-02-16
    • 1970-01-01
    • 2018-04-23
    • 2017-10-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多